From 9f1d9c78fa7f6b30e0f38bc150faa26e32fc5623 Mon Sep 17 00:00:00 2001 From: sunrisepeak Date: Thu, 17 Sep 2026 16:22:20 +0800 Subject: [PATCH 1/2] 0.7.0 --- follow openkal 0.13 The specification adds declarations and alters none that this package uses; the exact version requirement moves so that this package resolves in one graph with the rest of the 0.13 wave. Comments carry no emoji. --- .github/workflows/ci.yml | 74 ++++++++++++++++++------------------- README.md | 10 ++--- board.ld | 12 +++--- build.mcpp | 4 +- examples/hello/mcpp.toml | 2 +- examples/hello/src/main.cpp | 4 +- mcpp.toml | 10 ++--- src/env.cpp | 4 +- src/kal.cpp | 20 +++++----- src/sbi.h | 2 +- src/start.cpp | 24 ++++++------ src/time.cpp | 12 +++--- src/version.cpp | 2 +- 13 files changed, 90 insertions(+), 90 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9e4dba4..4911e53 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -41,7 +41,7 @@ jobs: - name: Install mcpp run: | - # ⚠️ A LOOP, BECAUSE ONE `xlings update` CAN RETURN A STALE INDEX + # A LOOP, BECAUSE ONE `xlings update` CAN RETURN A STALE INDEX # WITHOUT SAYING SO. # # The index is published as an artifact behind a pointer, and that @@ -62,7 +62,7 @@ jobs: # of the two situations it is. for attempt in 1 2 3 4 5 6; do xlings update > /dev/null 2>&1 || true - if # ⚠️ THE PIN MAY NAME THE RELEASE THIS RUN IS VALIDATING, which does + if # THE PIN MAY NAME THE RELEASE THIS RUN IS VALIDATING, which does # not exist yet — that is the whole point of MCPP_SOURCE_REF. Bootstrap # from whatever the index has; the step below replaces it with the # build under review, and the pin is what an ordinary run tests. @@ -78,7 +78,7 @@ jobs: echo "the index has not caught up yet (attempt $attempt of 6); waiting 60s" sleep 60 done - # ⚠️⚠️ TRANSITION: GIVE THE BOOTSTRAP THE glibc ITS BINDING NAMES. + # TRANSITION: GIVE THE BOOTSTRAP THE glibc ITS BINDING NAMES. # # `xim:glibc`'s `latest` moved from `2.44` to `2.44.2`. A payload # directory is named after the version a request RESOLVED to, while a @@ -90,13 +90,13 @@ jobs: # error: selected RuntimeBinding glibc@2.44 requires payload # '…/xpkgs/xim-x-glibc/2.44', but it is not installed # - # ⚠️ On every NEW machine and on none that already existed, which is why + # On every NEW machine and on none that already existed, which is why # it is invisible from a developer's own. Measured on `main` as readily # as on any branch — the index records the same failure verbatim in # `pkgs/g/glibc.lua` and states the rule it broke: "The index is DATA # and the client is a PROGRAM: the consumer ships first." # - # ⭐ REMOVE THIS once a released mcpp resolves it. `mcpp 2026.8.27.1` + # REMOVE THIS once a released mcpp resolves it. `mcpp 2026.8.27.1` # accepts an installed payload whose version REFINES the requested one # (`payload_dir_for_version`), so a bootstrap from it needs nothing # here. Until then the missing payload is simply installed. @@ -108,13 +108,13 @@ jobs: fi mcpp --version mcpp self config --mirror GLOBAL - # ⭐⭐ CROSS-VALIDATION: BUILD THE mcpp UNDER REVIEW AND USE THAT ONE. + # CROSS-VALIDATION: BUILD THE mcpp UNDER REVIEW AND USE THAT ONE. # # Empty in the ordinary run, so this job keeps testing the RELEASED # mcpp the pin above names. Set it — `workflow_dispatch` input, or the # repository variable — and the same job runs against that source. # - # ⚠️ THIS EXISTS BECAUSE THE ORDER USED TO BE WRONG. Several mcpp + # THIS EXISTS BECAUSE THE ORDER USED TO BE WRONG. Several mcpp # releases went out green and only then turned this ecosystem red: the # engine's own CI cannot see a defect that appears only in a real # dependency graph, and this repository could not see the engine until @@ -127,7 +127,7 @@ jobs: [ -d "$src" ] || git clone --quiet --depth 1 \ --branch "$MCPP_SOURCE_REF" \ https://github.com/mcpp-community/mcpp.git "$src" - # ⚠️ THE CLONE'S OWN WORKSPACE PIN MUST NOT DECIDE WHICH mcpp + # THE CLONE'S OWN WORKSPACE PIN MUST NOT DECIDE WHICH mcpp # BUILDS IT. `.xlings.json` at mcpp's root pins the mcpp that # compiles mcpp, and that pin does not move when mcpp is released — # so a build inside the checkout obeys it and tries to install a @@ -140,7 +140,7 @@ jobs: # above, which is exactly what removing the file leaves. rm -f "$src/.xlings.json" ( cd "$src" && mcpp build --release ) - # ⚠️ BOTH SPELLINGS, AND NO `-perm`. The matrix reaches Windows and + # BOTH SPELLINGS, AND NO `-perm`. The matrix reaches Windows and # macOS runners too: on Windows the artefact is `mcpp.exe`, and # `-perm -u+x` is not a question that filesystem answers the way this # expects. Measured: `Finished release [optimized] in 173.44s` @@ -154,13 +154,13 @@ jobs: \( -name mcpp -o -name mcpp.exe \) | head -1) [ -n "$built" ] || { echo "::error::mcpp did not build from $MCPP_SOURCE_REF"; exit 1; } echo "$(cd "$(dirname "$built")" && pwd)" >> "$GITHUB_PATH" - # ⚠️ Reported, because a PATH entry that does not win looks exactly + # Reported, because a PATH entry that does not win looks exactly # like one that does until something built with the wrong engine. echo "under review: $("$built" --version) (from $MCPP_SOURCE_REF)" fi - # ⚠️⚠️ A JOB THAT RESOLVES THE PUBLISHED SPECIFICATION CANNOT REVIEW A + # A JOB THAT RESOLVES THE PUBLISHED SPECIFICATION CANNOT REVIEW A # CHANGE TO ONE. # # Another step in this file already clones the specification and @@ -172,7 +172,7 @@ jobs: # synced index ... the index is current, so this name is either # wrong or not published yet # - # ⭐⭐ THE UNIT IS THE JOB, NOT THE REPOSITORY. Measured 2026-08-28 across + # THE UNIT IS THE JOB, NOT THE REPOSITORY. Measured 2026-08-28 across # the eight repositories of this ecosystem while one change spanned all of # them: seven jobs in three repositories had this shape, and every one of # those repositories ALSO had a job that substituted correctly --- which is @@ -192,11 +192,11 @@ jobs: else echo "the specification has no $OPENKAL_BRANCH; its default branch is used" fi - # ⚠️ EVERY MANIFEST THAT NAMES IT, AND BY THE SAME FORM. mcpp refuses + # EVERY MANIFEST THAT NAMES IT, AND BY THE SAME FORM. mcpp refuses # a graph in which one package reaches a dependency by version and # another by path, so substituting only the root leaves the build # refusing for a second reason instead of the first. - # ⚠️ NOT `sed -i'. This step runs on macOS and on Windows too, and + # NOT `sed -i'. This step runs on macOS and on Windows too, and # BSD sed requires an argument to -i that GNU sed refuses. A temporary # file is the spelling that holds on all three. subst() { # subst @@ -214,7 +214,7 @@ jobs: xlings install xim:qemu-riscv -y XLINGS_HOME="$HOME/.mcpp/registry" xlings install xim:qemu-riscv -y - # ⚠️ The assertion is on the OUTPUT, not on the exit status. A firmware + # The assertion is on the OUTPUT, not on the exit status. A firmware # that never reaches the payload exits zero, and so does a payload whose # console writes go nowhere — which is precisely the failure this backend # exists to avoid on a second machine. @@ -227,7 +227,7 @@ jobs: mcpp run 2>&1 | tee run.log grep -q "hello from openkal over SBI" run.log grep -q "heap ok" run.log - # ⚠️ `clock ok` is the line that distinguishes a counter that reads + # `clock ok` is the line that distinguishes a counter that reads # from a counter that MOVES. The example takes two readings with a # sleep between them; a stuck clock reads fine and prints # `clock stuck`. Verified to print it, by returning a constant from @@ -235,7 +235,7 @@ jobs: grep -q "clock ok" run.log grep -q "env empty" run.log - # ⭐⭐ THE HALF OF CLAUSE 9 THIS BACKEND WAS NOT PERFORMING. + # THE HALF OF CLAUSE 9 THIS BACKEND WAS NOT PERFORMING. # # The specification makes behavioural conformance a property of every # implementation, and three of the four in this ecosystem ran the suite @@ -244,7 +244,7 @@ jobs: # language, does not import std, and states in its own manifest that it is # written to run in a program that carries no other runtime. # - # ⚠️ What it needed was three things this environment supplies and a + # What it needed was three things this environment supplies and a # hosted one does not have to, and each was found by trying: # # the memory map — now `openkal-opensbi/board.ld`, reaching the @@ -260,7 +260,7 @@ jobs: # function and the startup object refers to it # by name. # - # ⚠️ THE ASSERTION IS ON THE OUTPUT AND ON THE EXIT STATUS BOTH. The suite + # THE ASSERTION IS ON THE OUTPUT AND ON THE EXIT STATUS BOTH. The suite # exits 2 when it observed nothing, which is the outcome a selection that # matched no interface would otherwise pass silently — and `core` on a # machine with no operating system is exactly the selection where that @@ -283,7 +283,7 @@ jobs: bash tools/run-conformance.sh openkal-opensbi "$GITHUB_WORKSPACE" core \ --target riscv64-none-elf 2>&1 | tee conf.log grep -q "the implementation conforms in every observation made" conf.log - # ⚠️ And that something WAS observed. "0 did not hold" is also what a + # And that something WAS observed. "0 did not hold" is also what a # run that examined nothing reports. grep -qE "observations: [1-9][0-9]* held" conf.log @@ -296,7 +296,7 @@ jobs: # A package that has only ever been built from Linux is a package whose # consumers must use Linux, and nothing in these sources says so. # - # ⚠️ A TOOLCHAIN AXIS IS ABSENT HERE, AND THAT IS MEASURED RATHER THAN + # A TOOLCHAIN AXIS IS ABSENT HERE, AND THAT IS MEASURED RATHER THAN # ASSUMED. The row for a bare-metal triple names its compiler, and the # command-line override does not displace it: `--toolchain gcc@16.1.0` on a # `riscv64-none-elf` build resolves llvm@22.1.8 regardless. A matrix over @@ -305,7 +305,7 @@ jobs: # choice is real — openkal, whose declarations are compiled by three families # on three systems. # - # ⚠️ BUILD ONLY, AND DELIBERATELY. Behaviour is asserted once, above, under an + # BUILD ONLY, AND DELIBERATELY. Behaviour is asserted once, above, under an # emulator. Booting the same image from three systems would be a statement # about the emulator rather than about this package, and "the image does what # the README says" does not become more true for having been observed from @@ -349,7 +349,7 @@ jobs: - name: Install mcpp run: | - # ⚠️ A LOOP, BECAUSE ONE `xlings update` CAN RETURN A STALE INDEX + # A LOOP, BECAUSE ONE `xlings update` CAN RETURN A STALE INDEX # WITHOUT SAYING SO. # # The index is published as an artifact behind a pointer, and that @@ -370,7 +370,7 @@ jobs: # of the two situations it is. for attempt in 1 2 3 4 5 6; do xlings update > /dev/null 2>&1 || true - if # ⚠️ THE PIN MAY NAME THE RELEASE THIS RUN IS VALIDATING, which does + if # THE PIN MAY NAME THE RELEASE THIS RUN IS VALIDATING, which does # not exist yet — that is the whole point of MCPP_SOURCE_REF. Bootstrap # from whatever the index has; the step below replaces it with the # build under review, and the pin is what an ordinary run tests. @@ -386,7 +386,7 @@ jobs: echo "the index has not caught up yet (attempt $attempt of 6); waiting 60s" sleep 60 done - # ⚠️⚠️ TRANSITION: GIVE THE BOOTSTRAP THE glibc ITS BINDING NAMES. + # TRANSITION: GIVE THE BOOTSTRAP THE glibc ITS BINDING NAMES. # # `xim:glibc`'s `latest` moved from `2.44` to `2.44.2`. A payload # directory is named after the version a request RESOLVED to, while a @@ -398,13 +398,13 @@ jobs: # error: selected RuntimeBinding glibc@2.44 requires payload # '…/xpkgs/xim-x-glibc/2.44', but it is not installed # - # ⚠️ On every NEW machine and on none that already existed, which is why + # On every NEW machine and on none that already existed, which is why # it is invisible from a developer's own. Measured on `main` as readily # as on any branch — the index records the same failure verbatim in # `pkgs/g/glibc.lua` and states the rule it broke: "The index is DATA # and the client is a PROGRAM: the consumer ships first." # - # ⭐ REMOVE THIS once a released mcpp resolves it. `mcpp 2026.8.27.1` + # REMOVE THIS once a released mcpp resolves it. `mcpp 2026.8.27.1` # accepts an installed payload whose version REFINES the requested one # (`payload_dir_for_version`), so a bootstrap from it needs nothing # here. Until then the missing payload is simply installed. @@ -416,13 +416,13 @@ jobs: fi mcpp --version mcpp self config --mirror GLOBAL - # ⭐⭐ CROSS-VALIDATION: BUILD THE mcpp UNDER REVIEW AND USE THAT ONE. + # CROSS-VALIDATION: BUILD THE mcpp UNDER REVIEW AND USE THAT ONE. # # Empty in the ordinary run, so this job keeps testing the RELEASED # mcpp the pin above names. Set it — `workflow_dispatch` input, or the # repository variable — and the same job runs against that source. # - # ⚠️ THIS EXISTS BECAUSE THE ORDER USED TO BE WRONG. Several mcpp + # THIS EXISTS BECAUSE THE ORDER USED TO BE WRONG. Several mcpp # releases went out green and only then turned this ecosystem red: the # engine's own CI cannot see a defect that appears only in a real # dependency graph, and this repository could not see the engine until @@ -435,7 +435,7 @@ jobs: [ -d "$src" ] || git clone --quiet --depth 1 \ --branch "$MCPP_SOURCE_REF" \ https://github.com/mcpp-community/mcpp.git "$src" - # ⚠️ THE CLONE'S OWN WORKSPACE PIN MUST NOT DECIDE WHICH mcpp + # THE CLONE'S OWN WORKSPACE PIN MUST NOT DECIDE WHICH mcpp # BUILDS IT. `.xlings.json` at mcpp's root pins the mcpp that # compiles mcpp, and that pin does not move when mcpp is released — # so a build inside the checkout obeys it and tries to install a @@ -448,7 +448,7 @@ jobs: # above, which is exactly what removing the file leaves. rm -f "$src/.xlings.json" ( cd "$src" && mcpp build --release ) - # ⚠️ BOTH SPELLINGS, AND NO `-perm`. The matrix reaches Windows and + # BOTH SPELLINGS, AND NO `-perm`. The matrix reaches Windows and # macOS runners too: on Windows the artefact is `mcpp.exe`, and # `-perm -u+x` is not a question that filesystem answers the way this # expects. Measured: `Finished release [optimized] in 173.44s` @@ -462,13 +462,13 @@ jobs: \( -name mcpp -o -name mcpp.exe \) | head -1) [ -n "$built" ] || { echo "::error::mcpp did not build from $MCPP_SOURCE_REF"; exit 1; } echo "$(cd "$(dirname "$built")" && pwd)" >> "$GITHUB_PATH" - # ⚠️ Reported, because a PATH entry that does not win looks exactly + # Reported, because a PATH entry that does not win looks exactly # like one that does until something built with the wrong engine. echo "under review: $("$built" --version) (from $MCPP_SOURCE_REF)" fi - # ⚠️⚠️ A JOB THAT RESOLVES THE PUBLISHED SPECIFICATION CANNOT REVIEW A + # A JOB THAT RESOLVES THE PUBLISHED SPECIFICATION CANNOT REVIEW A # CHANGE TO ONE. # # Another step in this file already clones the specification and @@ -480,7 +480,7 @@ jobs: # synced index ... the index is current, so this name is either # wrong or not published yet # - # ⭐⭐ THE UNIT IS THE JOB, NOT THE REPOSITORY. Measured 2026-08-28 across + # THE UNIT IS THE JOB, NOT THE REPOSITORY. Measured 2026-08-28 across # the eight repositories of this ecosystem while one change spanned all of # them: seven jobs in three repositories had this shape, and every one of # those repositories ALSO had a job that substituted correctly --- which is @@ -500,11 +500,11 @@ jobs: else echo "the specification has no $OPENKAL_BRANCH; its default branch is used" fi - # ⚠️ EVERY MANIFEST THAT NAMES IT, AND BY THE SAME FORM. mcpp refuses + # EVERY MANIFEST THAT NAMES IT, AND BY THE SAME FORM. mcpp refuses # a graph in which one package reaches a dependency by version and # another by path, so substituting only the root leaves the build # refusing for a second reason instead of the first. - # ⚠️ NOT `sed -i'. This step runs on macOS and on Windows too, and + # NOT `sed -i'. This step runs on macOS and on Windows too, and # BSD sed requires an argument to -i that GNU sed refuses. A temporary # file is the spelling that holds on all three. subst() { # subst @@ -516,7 +516,7 @@ jobs: subst mcpp.toml .spec - name: The backend cross-builds run: | - # ⚠️ TWICE, AND THE FIRST IS ALLOWED TO FAIL — every row of this + # TWICE, AND THE FIRST IS ALLOWED TO FAIL — every row of this # matrix is a machine that has never targeted this triple, which is # precisely where mcpp's lazy install of the target C library shows. # The first build compiles sources needing its headers before they diff --git a/README.md b/README.md index cba817a..89a77cd 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ openkal = "0.9.0" openkal-opensbi = "0.3.0" ``` -## ⭐ The portable RISC-V backend, as distinct from a board's own +## The portable RISC-V backend, as distinct from a board's own A board-supplied backend writes to a device address, and that address is a board fact. The same binary on a second RISC-V machine writes to something that is not @@ -44,7 +44,7 @@ None of the five is a deviation. Clause 6.1 makes an interface an implementation does not provide absent at the link, so a program requiring one is refused when it is built rather than when it runs. -⚠️ **`time` used to be on that list, with a reason, and the reason was wrong.** +**`time` used to be on that list, with a reason, and the reason was wrong.** It read: SBI can arm a timer interrupt, which is a mechanism for a kernel rather than a clock a program can read. The first half is true. The second does not @@ -60,7 +60,7 @@ kernel beneath: t0=333572 t1=381292 ADVANCES ``` -⭐ The conclusion got rechecked and the reason beside it did not. The two +The conclusion got rechecked and the reason beside it did not. The two minutes that refuted it had been available for as long as the file existed. `time` is therefore provided: a monotonic count, an exact granularity, and a @@ -103,7 +103,7 @@ run here carried a copy: `examples/hello` had one, the C++ runtime's `same-source` example had a second, and the specification's conformance suite would have needed a third. None of those is a property of a program. -⚠️ **A program that states one as well states it twice.** The fact reaches +**A program that states one as well states it twice.** The fact reaches consumers transitively, and two linker scripts are both applied — which fails as overlapping output sections and says nothing about there being two: @@ -126,7 +126,7 @@ v2.0, and older firmware answers `SBI_ERR_NOT_SUPPORTED` — on which every writ would silently transfer nothing. The legacy one-character extension is the fallback. -⚠️ **No function-local `static`.** A guarded local static compiles to +**No function-local `static`.** A guarded local static compiles to `__cxa_guard_acquire`/`__cxa_guard_release`, which a freestanding target has no runtime to supply. Measured: the link fails naming both. `-fno-threadsafe-statics` would also silence it, but a flag that has to be remembered is weaker than a diff --git a/board.ld b/board.ld index a7f693c..b11496a 100644 --- a/board.ld +++ b/board.ld @@ -1,7 +1,7 @@ /* The memory map of a program this implementation starts, and the symbols its * startup object reads. * - * ⭐⭐ THIS FILE IS A BOARD FACT AND THEREFORE BELONGS TO THIS PACKAGE. + * THIS FILE IS A BOARD FACT AND THEREFORE BELONGS TO THIS PACKAGE. * * Until now every program that wanted to run over OpenSBI carried its own copy: * `examples/hello` had one, `openkal-llvm-runtime/examples/same-source` had a @@ -9,7 +9,7 @@ * The load address is not a property of any of them — it is where this firmware * hands control over, which is precisely what this package exists to know. * - * ⚠️ Measured 2026-08-23: the conformance suite BUILDS for `riscv64-none-elf` + * Measured 2026-08-23: the conformance suite BUILDS for `riscv64-none-elf` * against this implementation and then produces an image whose entry point is * 0x0, because nothing placed it. The suite is written to run in a program that * carries no other runtime, and asking it to carry a board's memory map would @@ -19,7 +19,7 @@ * ⇒ Supplied through `build.mcpp`, which reaches the CONSUMER's link line. A * program adds nothing and gets a layout that works. * - * ⚠️ THE SIZES ARE GENEROUS RATHER THAN MINIMAL, and that is the one judgement + * THE SIZES ARE GENEROUS RATHER THAN MINIMAL, and that is the one judgement * in this file. A C program printing a string needs neither 256 KiB of stack * nor 16 MiB of heap; a program carrying a C library and a C++ standard library * does, and it exhausts the smaller figures during its own initialisation — @@ -32,7 +32,7 @@ * OpenSBI occupies 0x80000000 upward and hands control to the next stage at * 0x80200000, which is why this address and not the start of RAM. * - * ⚠️ FIRMWARE JUMPS TO THE LOWEST LOADED ADDRESS AND NOT TO THE ENTRY THE IMAGE + * FIRMWARE JUMPS TO THE LOWEST LOADED ADDRESS AND NOT TO THE ENTRY THE IMAGE * RECORDS. Measured 2026-08-23, after an attempt to put the ELF header inside * the first loaded segment so that `__ehdr_start` would be usable: the entry * moved to 0x80200270, OpenSBI still announced `Next Address 0x80200000`, and @@ -40,7 +40,7 @@ * the load address has to be the first instruction, and everything that would * otherwise be read out of the program headers is named here instead. * - * ⚠️ FOUR THINGS BEYOND THE MINIMUM, AND EACH IS SOMETHING A C++ PROGRAM HAS + * FOUR THINGS BEYOND THE MINIMUM, AND EACH IS SOMETHING A C++ PROGRAM HAS * THAT A C ONE DOES NOT. * * The initialiser arrays. Every static object with a constructor puts a @@ -127,7 +127,7 @@ SECTIONS { /* 256 KiB of stack. See the note above. */ . = ALIGN(16); . = . + 0x40000; __stack_top = .; - /* ⭐ AND THE HEAP, WHICH FOR THIS PROGRAM CANNOT BE THE IMPLEMENTATION'S + /* AND THE HEAP, WHICH FOR THIS PROGRAM CANNOT BE THE IMPLEMENTATION'S * DEFAULT. * * openkal-opensbi carries a 64 KiB static region for a program that diff --git a/build.mcpp b/build.mcpp index 7f3a3e9..95d297c 100644 --- a/build.mcpp +++ b/build.mcpp @@ -1,13 +1,13 @@ import mcpp; -// ⭐ THE BOARD'S MEMORY MAP, PUT ON THE CONSUMER'S LINK LINE. +// THE BOARD'S MEMORY MAP, PUT ON THE CONSUMER'S LINK LINE. // // `board.ld` records where this firmware hands control over and what a program // started that way needs its layout to contain. Both are facts about this // environment rather than about any program, which is why they are here and not // copied into each one — see the head of that file for what the copies were. // -// ⚠️ `link_script` reaches the CONSUMER's link line, and a relative path in +// `link_script` reaches the CONSUMER's link line, and a relative path in // `ldflags` would resolve against the build directory instead of against this // package. That is the same reason `openkal-macos` supplies its stub through a // `link_search` rather than a path in a flag. diff --git a/examples/hello/mcpp.toml b/examples/hello/mcpp.toml index ed13128..e0ac7a2 100644 --- a/examples/hello/mcpp.toml +++ b/examples/hello/mcpp.toml @@ -13,7 +13,7 @@ runner = ["qemu-system-riscv64", "-machine", "virt", "-nographic", "-no-reboot", "-bios", "default", "-kernel"] [dependencies] -# ⚠️ THE FORM MUST MATCH THE ONE THE IMPLEMENTATION USES, not merely the +# THE FORM MUST MATCH THE ONE THE IMPLEMENTATION USES, not merely the # version. mcpp refuses a graph in which one package reaches a dependency by # version and another by git: # diff --git a/examples/hello/src/main.cpp b/examples/hello/src/main.cpp index d1d302b..f5f48f1 100644 --- a/examples/hello/src/main.cpp +++ b/examples/hello/src/main.cpp @@ -1,6 +1,6 @@ // openkal over SBI, with no C library and no board package beneath it. // -// ⚠️ The entry point is `_start` and not `main`: nothing here supplies a C +// The entry point is `_start` and not `main`: nothing here supplies a C // runtime, so there is no crt0 to call one. OpenSBI hands control to the image // at its load address in supervisor mode with a stack that the linker script // below establishes. @@ -27,7 +27,7 @@ extern "C" void kmain() { say(p ? "heap ok\n" : "heap exhausted\n"); kal_free(p, 64, 16); - // ⚠️ THE ASSERTION IS THAT IT MOVES, NOT THAT IT READS. + // THE ASSERTION IS THAT IT MOVES, NOT THAT IT READS. // // A clock that returns a constant reads perfectly well and is worthless, // and it is the exact failure the comment this interface replaced was diff --git a/mcpp.toml b/mcpp.toml index cff2cc2..7f7f48e 100644 --- a/mcpp.toml +++ b/mcpp.toml @@ -1,6 +1,6 @@ # openkal on the RISC-V Supervisor Binary Interface. # -# ⭐ THE PORTABLE RISC-V BACKEND, AS DISTINCT FROM A BOARD'S OWN. +# THE PORTABLE RISC-V BACKEND, AS DISTINCT FROM A BOARD'S OWN. # # A board-supplied backend writes to a device address, and that address is a # board fact: the same binary on a second RISC-V machine writes to something @@ -14,7 +14,7 @@ [package] namespace = "mcpplibs" name = "openkal-opensbi" -version = "0.6.0" +version = "0.7.0" description = "An implementation of openkal on the RISC-V Supervisor Binary Interface, portable across every machine whose firmware provides one" license = "Apache-2.0" @@ -33,9 +33,9 @@ repo = "https://github.com/mcpplibs/openkal-opensbi" # The contract, not an implementation of it. Declaring it turns a version # mismatch into a resolution-time message rather than a link-time one. [dependencies] -openkal = "0.12.0" +openkal = "0.13.0" -# ⭐ WHAT RECEIVES CONTROL, WHICH IS A STATEMENT ABOUT THE PROGRAM. +# WHAT RECEIVES CONTROL, WHICH IS A STATEMENT ABOUT THE PROGRAM. # # A program that already carries a runtime has an entry object of its own and # must not get a second. A program that does not — one whose C library is @@ -61,7 +61,7 @@ flags = [ "-fno-asynchronous-unwind-tables"] }, ] -# ⚠️ TWO FIGURES THAT BELONG TO THE MACHINE, DECLARED RATHER THAN ASSUMED. +# TWO FIGURES THAT BELONG TO THE MACHINE, DECLARED RATHER THAN ASSUMED. # # The heap size is a build input because SBI provides no allocator and the # region therefore has to come from somewhere. 64 KiB is enough for the diff --git a/src/env.cpp b/src/env.cpp index 4765c17..c3c5669 100644 --- a/src/env.cpp +++ b/src/env.cpp @@ -1,6 +1,6 @@ // openkal.env on the RISC-V Supervisor Binary Interface. // -// ⚠️ EVERY ANSWER HERE IS EMPTY, AND THAT IS AN IMPLEMENTATION RATHER THAN A +// EVERY ANSWER HERE IS EMPTY, AND THAT IS AN IMPLEMENTATION RATHER THAN A // STUB. THE DIFFERENCE IS THE ONE CLAUSE 6.2 TURNS ON. // // Clause 6.2 forbids the arrangement this file could be mistaken for: "an @@ -18,7 +18,7 @@ // this one returns for the first of none, by the same rule, and no caller needs // a special case for either. // -// ⚠️ WHY IT IS EMPTY, WHICH IS A FACT ABOUT THE ENTRY CONTRACT AND NOT ABOUT SBI +// WHY IT IS EMPTY, WHICH IS A FACT ABOUT THE ENTRY CONTRACT AND NOT ABOUT SBI // // Firmware enters the image at its load address with a hart identifier and a // device tree in registers. Neither is a command line. A device tree CAN carry diff --git a/src/kal.cpp b/src/kal.cpp index 2175caf..e2a35c7 100644 --- a/src/kal.cpp +++ b/src/kal.cpp @@ -9,7 +9,7 @@ // // SBI has no such property. The console here is a call into firmware that // already knows the machine, so one binary runs under OpenSBI on QEMU's `virt` -// and on a real board without being rebuilt. ⭐ That makes this the portable +// and on a real board without being rebuilt. That makes this the portable // RISC-V backend and the board's the specific one — and a project picks by // which property it needs, not by which is better. // @@ -22,7 +22,7 @@ // clause 6.2 says the remedy for an operation that cannot be provided is that // its absence be expressed by its absence rather than by a run-time refusal. // -// ⚠️ `time` USED TO BE ON THAT LIST, WITH A REASON, AND THE REASON WAS WRONG. +// `time` USED TO BE ON THAT LIST, WITH A REASON, AND THE REASON WAS WRONG. // // It read: SBI can arm a timer interrupt, which is a mechanism for a kernel // rather than a clock a program can read. The first half is true; the second @@ -42,12 +42,12 @@ constexpr kal_uintptr kStdin = 0; constexpr kal_uintptr kStdout = 1; constexpr kal_uintptr kStderr = 2; -// ⚠️ Probed once rather than assumed. DBCN arrived in SBI v2.0, and firmware +// Probed once rather than assumed. DBCN arrived in SBI v2.0, and firmware // older than that answers `SBI_ERR_NOT_SUPPORTED` — on which every write would // silently transfer nothing. The legacy extension is one character per trap and // is deprecated, which is exactly why it is the fallback and not the default. // -// ⚠️ A tri-state file-scope variable, and NOT a function-local `static`. +// A tri-state file-scope variable, and NOT a function-local `static`. // // A guarded local static compiles to `__cxa_guard_acquire`/`__cxa_guard_release` // — thread-safe initialisation supplied by the C++ runtime, which a @@ -104,7 +104,7 @@ kal_intptr write_all(const unsigned char* p, kal_uintptr n) { // silently wrong is a simulation. Exhaustion is a defined outcome — `kal_alloc` // returns null — and every caller already has to handle it. // -// ⚠️ `kal_free` therefore does nothing, and that is stated rather than hidden. +// `kal_free` therefore does nothing, and that is stated rather than hidden. // A program whose allocation pattern needs reuse should place a real allocator // above this one; that is a policy decision, and openkal carries mechanism. alignas(16) unsigned char g_heap[OPENKAL_OPENSBI_HEAP_BYTES]; @@ -112,7 +112,7 @@ kal_uintptr g_used = 0; } // namespace -// ⭐ AND THE PROGRAM MAY SAY WHERE INSTEAD, FOR THE SAME REASON IT SAYS WHERE +// AND THE PROGRAM MAY SAY WHERE INSTEAD, FOR THE SAME REASON IT SAYS WHERE // THE STACK IS. // // The region above is a static array, which means its size is in the image and @@ -121,7 +121,7 @@ kal_uintptr g_used = 0; // carries a C library and a C++ standard library allocates during its own // initialisation, before `main`, and 64 KiB does not survive it. // -// ⚠️ AND THE WAY THAT SHOWS IS NOT A DIAGNOSTIC. Measured 2026-08-23: a +// AND THE WAY THAT SHOWS IS NOT A DIAGNOSTIC. Measured 2026-08-23: a // bare-metal `import std;` program linked, started, and printed NOTHING — the // allocator ran out inside the standard library's static initialisation, before // any stream existed to report it on. A message would have needed the very @@ -146,7 +146,7 @@ namespace { struct region { unsigned char* base; kal_uintptr size; }; region heap_region() { - // ⚠️ `+` on each: these are arrays, and comparing two arrays directly is + // `+` on each: these are arrays, and comparing two arrays directly is // deprecated in this dialect because it compares addresses while reading // like a comparison of contents. Decaying them says which was meant. if (+__heap_start != nullptr && +__heap_end > +__heap_start) @@ -183,7 +183,7 @@ kal_stream kal_stderr(void) { return kal_stream{kStderr}; } kal_intptr kal_stream_write(kal_stream s, const void* buf, kal_uintptr n) { if (s.h != kStdout && s.h != kStderr) return -kal_err_invalid; - // ⚠️ Both streams reach the same console. SBI has one, and reporting two + // Both streams reach the same console. SBI has one, and reporting two // that are secretly one would be a claim the firmware cannot honour. return write_all(static_cast(buf), n); } @@ -250,7 +250,7 @@ void kal_free(void*, kal_uintptr, kal_uintptr) {} // ── The interfaces this machine does not have are absent, and stay absent ─── // -// ⚠️ NO `kal_fs_props`, NO `kal_task_props`, AND THAT IS THE MECHANISM RATHER +// NO `kal_fs_props`, NO `kal_task_props`, AND THAT IS THE MECHANISM RATHER // THAN AN OMISSION. // // 0.1.3 defined both as zero, because a capability-querying program failed to diff --git a/src/sbi.h b/src/sbi.h index 00b1056..8c17614 100644 --- a/src/sbi.h +++ b/src/sbi.h @@ -3,7 +3,7 @@ * SBI is the interface a RISC-V supervisor has to the firmware beneath it. It * is invoked with `ecall`: the extension identifier in a7, the function * identifier in a6, arguments in a0-a5, and a two-word result in a0 (an error - * code) and a1 (a value). ⚠️ That shape is the same two-word return openkal + * code) and a1 (a value). That shape is the same two-word return openkal * specifies for its own results, and for the same reason — it is what crosses a * privilege boundary in registers on this architecture. * diff --git a/src/start.cpp b/src/start.cpp index dc0c98f..3633baa 100644 --- a/src/start.cpp +++ b/src/start.cpp @@ -5,7 +5,7 @@ // fact about what hands control over, and a consumer that contained these steps // would contain a copy of them per environment. // -// ⚠️ WHAT FIRMWARE HANDS OVER, AND WHAT IT DOES NOT. +// WHAT FIRMWARE HANDS OVER, AND WHAT IT DOES NOT. // // A kernel starts a program with arguments on the stack, a thread pointer to // establish, program headers to report, and a stack already there. Firmware @@ -19,7 +19,7 @@ // exist, and it stops. And it does not do the thing the other spends most of // its length on, because there is nothing to read. // -// ⚠️ THE STACK COMES FROM THE PROGRAM'S LINKER SCRIPT AND CANNOT COME FROM HERE. +// THE STACK COMES FROM THE PROGRAM'S LINKER SCRIPT AND CANNOT COME FROM HERE. // // `__stack_top' is defined by the linker script the program supplies, because // where the stack goes is a statement about the image's layout and the image is @@ -48,7 +48,7 @@ int main(int, char**, char**); using initialiser = void (*)(int, char**, char**); -// ⚠️ NOT in an anonymous namespace, and that is the compiler's rule rather than +// NOT in an anonymous namespace, and that is the compiler's rule rather than // a preference: internal linkage and a weak declaration are contradictory, and // clang says so in as many words. The linker script defines these, and a // program built without one gets the null range the weak declaration is for. @@ -60,7 +60,7 @@ using initialiser = void (*)(int, char**, char**); namespace { void run_initialisers() { - // ⚠️ Only when no C library took the hand-over. One that did runs these + // Only when no C library took the hand-over. One that did runs these // itself, and running them twice constructs every static object twice. static char* nothing = nullptr; for (initialiser* p = __preinit_array_start; p != __preinit_array_end; ++p) @@ -71,14 +71,14 @@ void run_initialisers() { } // namespace -// ⭐⭐ THE THREAD POINTER, WHICH IS THE OTHER THING A KERNEL WOULD HAVE DONE. +// THE THREAD POINTER, WHICH IS THE OTHER THING A KERNEL WOULD HAVE DONE. // // openkal-linux's start object establishes it too, and for the same reason: the // register that names the current context's thread-local storage is set by // whoever creates the context, and where a program carries no loader, that is // the implementation. // -// ⚠️ WHAT IT LOOKS LIKE WHEN IT IS MISSING IS NOT "NO THREAD-LOCAL STORAGE". +// WHAT IT LOOKS LIKE WHEN IT IS MISSING IS NOT "NO THREAD-LOCAL STORAGE". // // Measured 2026-08-23. A bare-metal `import std;` program started, printed, and // faulted at the first `throw`: @@ -91,12 +91,12 @@ void run_initialisers() { // about the message says "thread pointer": it names an exception function and // an address, and both look like memory corruption. // -// ⚠️ AND THE C LIBRARY DOES NOT COVER THIS. openkal-musl keeps ITS OWN thread +// AND THE C LIBRARY DOES NOT COVER THIS. openkal-musl keeps ITS OWN thread // pointer in a variable rather than in the register --- that is what lets it // run where the register means nothing --- so musl's startup succeeding says // nothing about whether the TOOLCHAIN's thread-locals work. Two mechanisms, // and only one of them was established. -// ⚠️ FROM THE LINKER SCRIPT, NOT FROM THE PROGRAM HEADERS. +// FROM THE LINKER SCRIPT, NOT FROM THE PROGRAM HEADERS. // // The obvious source is PT_TLS, reached through `__ehdr_start`. That requires // the ELF header to lie inside a loaded segment, which requires it to be at the @@ -124,7 +124,7 @@ kal_uintptr round_up(kal_uintptr n, kal_uintptr to) { return (n + to - 1) & ~(to // it as `TLS_ABOVE_TP` with `GAP_ABOVE_TP 0` --- which is where this was taken // from rather than from memory. void establish_thread_pointer() { - // ⚠️ These symbols carry their VALUE in their ADDRESS. A linker script + // These symbols carry their VALUE in their ADDRESS. A linker script // assignment defines an absolute symbol; there is no object to load from, // and reading one as if there were gives whatever lies at that address. const auto filesz = reinterpret_cast(__tls_filesz); @@ -153,7 +153,7 @@ void establish_thread_pointer() { } // namespace -// ⭐ WHAT crtbegin WOULD HAVE SUPPLIED, AND WHY ITS ABSENCE IS A LINK ERROR +// WHAT crtbegin WOULD HAVE SUPPLIED, AND WHY ITS ABSENCE IS A LINK ERROR // ABOUT A RELOCATION RANGE RATHER THAN ABOUT A MISSING NAME. // // Every static object with a destructor registers it through `__cxa_atexit`, @@ -166,7 +166,7 @@ void establish_thread_pointer() { // relocation R_RISCV_PCREL_HI20 out of range: -525086 // references '__dso_handle' // -// ⚠️ A reader who has not seen this before will read that as a code-model +// A reader who has not seen this before will read that as a code-model // problem, and the code model is already the widest one. The problem is that // the symbol is not in the image. Defining it here puts it in the image, and // the value is its own address because that is what identifies an image @@ -177,7 +177,7 @@ extern "C" { void* __dso_handle = &__dso_handle; } // the sequence needs nothing to have been set up before it runs --- which is // the situation it is in. // -// ⚠️ In `.text.entry` rather than `.text`, because the linker script places +// In `.text.entry` rather than `.text`, because the linker script places // that section first. Firmware jumps to the load address, not to `_start`: the // entry recorded in the image header is not read by firmware that loads a raw // image, so the first instruction at the load address has to BE this one. diff --git a/src/time.cpp b/src/time.cpp index 50bc519..010f6a3 100644 --- a/src/time.cpp +++ b/src/time.cpp @@ -1,6 +1,6 @@ // openkal.time on the RISC-V Supervisor Binary Interface. // -// ⚠️ THIS FILE EXISTS BECAUSE THE REASON RECORDED FOR ITS ABSENCE WAS WRONG. +// THIS FILE EXISTS BECAUSE THE REASON RECORDED FOR ITS ABSENCE WAS WRONG. // // kal.cpp said, and said it as a design decision rather than as a note: // @@ -21,7 +21,7 @@ // // t0=333572 t1=381292 ADVANCES // -// ⭐ The lesson is the one the repository keeps relearning: a conclusion gets +// The lesson is the one the repository keeps relearning: a conclusion gets // rechecked and the reason written beside it does not. The reason above sat in // a comment for as long as the file existed, and the two minutes that refuted // it were available the whole time. @@ -32,7 +32,7 @@ // the same counter, which on a machine with one execution context and no // scheduler is what sleeping is rather than a simulation of it. // -// ⚠️ NOT a wall clock. SBI defines no facility for one, and no board fact would +// NOT a wall clock. SBI defines no facility for one, and no board fact would // supply it either --- a real-time clock is a device, and reading it is what a // board backend does. `KAL_TIME_PROP_WALL_AVAILABLE` is left clear, which is // the specification's own way of saying so: clause 6.2 makes availability of a @@ -45,7 +45,7 @@ namespace { -// ⚠️ THE ONE BOARD FACT THIS PACKAGE TAKES, AND IT TAKES IT AS AN INPUT. +// THE ONE BOARD FACT THIS PACKAGE TAKES, AND IT TAKES IT AS AN INPUT. // // `rdtime` counts at a rate the architecture does not fix. The rate is // published in the device tree as `/cpus/timebase-frequency`, and this package @@ -59,7 +59,7 @@ namespace { // project that knows which machine, rather than assumed by a package that does // not. The default is QEMU's `virt`, which is what the example runs on. // -// ⚠️ A project on other hardware that leaves the default in place gets a clock +// A project on other hardware that leaves the default in place gets a clock // that advances at the wrong rate. That is a stated bound and not a hidden one: // the figure has a name, the name appears in the manifest, and this comment is // what a reader finds when they look for it. @@ -105,7 +105,7 @@ kal_duration kal_time_monotonic_granularity(void) { return g ? g : 1; } -// ⚠️ Spinning, and that is the accurate implementation rather than a stand-in. +// Spinning, and that is the accurate implementation rather than a stand-in. // // Sleeping means giving the machine to something else until a time arrives. On // a machine with one execution context and nothing to give it to, the time diff --git a/src/version.cpp b/src/version.cpp index eb214a0..ebd1cb1 100644 --- a/src/version.cpp +++ b/src/version.cpp @@ -11,7 +11,7 @@ extern "C" { kal_u64 kal_version(void) { return KAL_VERSION; } -// ⚠️ THE WORD AGREES WITH WHAT IS EXPORTED, WHICH IS THE WHOLE OF ITS VALUE. +// THE WORD AGREES WITH WHAT IS EXPORTED, WHICH IS THE WHOLE OF ITS VALUE. // This machine has no storage, no second image and no scheduler, so // `openkal.fs', `openkal.process' and `openkal.task' are absent as definitions // --- and the word says so rather than leaving a consumer to discover it by From b63dbc93b1827988621a02ba67c8edeb1d4c8bf9 Mon Sep 17 00:00:00 2001 From: sunrisepeak Date: Thu, 17 Sep 2026 17:47:38 +0800 Subject: [PATCH 2/2] README: the install line names this release --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 89a77cd..70ec017 100644 --- a/README.md +++ b/README.md @@ -4,8 +4,8 @@ An implementation of [openkal][kal] on the RISC-V Supervisor Binary Interface. ```toml [dependencies] -openkal = "0.9.0" -openkal-opensbi = "0.3.0" +openkal = "0.13.0" +openkal-opensbi = "0.7.0" ``` ## The portable RISC-V backend, as distinct from a board's own