Repository navigation
Conversation
…native rate, codec volume The design round for A2 to A6 of the AMD bench's desktop. Nothing is built; the design and its roast are the pull request's body, and the build drops this commit. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015xhaydXCVRNscoccHYFUWy
Measurement: soundserver's resampler against the analytic sineA scratch crate on the arm64 dev host,
Commands, from the scratch crate's directory. In cargo's
|
Two needs the AMD bench's demo build found that no issue held: - The bench's keyboard acks both bytes of the scancode-set query and never sends the set byte, which main reads as Silent and answers by disabling the keyboard. The wait spends the keyboard stage that 0xF4 shares, and it costs 750 ms of every boot. #877's A2 is its design. - lib/hda asks every converter for 44100 Hz, and the bench's speaker converter offers 48000 Hz alone. The issue carries the owner's ruling on the rate and the resampler measurement posted on #877. #877's A5 is its design. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015xhaydXCVRNscoccHYFUWy
Two needs the AMD bench's demo build found that no issue held: - The bench's keyboard acks both bytes of the scancode-set query and never sends the set byte, which main reads as Silent and answers by disabling the keyboard. The wait spends the keyboard stage that 0xF4 shares, and it costs 750 ms of every boot. #877's A2 is its design. - lib/hda asks every converter for 44100 Hz, and the bench's speaker converter offers 48000 Hz alone. The issue carries the owner's ruling on the rate and the resampler measurement posted on #877. #877's A5 is its design. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015xhaydXCVRNscoccHYFUWy
ec0165c to
b53d9ba
Compare
|
Owner's ruling on the resampler, recorded by the orchestrator. He was shown #877 (comment): today's settings lose 0.31 dB at 20 kHz, and sinc 512 with 256× oversampling meets the 16-bit bound across the audible band at about 3× the resampling CPU and 512 KiB per resampled client. He chose full quality. A5 uses the settings that meet the bound, and only machines that resample pay the cost; the T14 does not. |
Design review, round 1: head
|
…sign round has them The design review of #877 (issuecomment-6121280458) sent both issues back with the design: - The keyboard's exit no longer asks a host test to hold that an exchange stopped before both acks disables the keyboard: sorting the exchange stays in the kernel's port I/O, where no host test reaches it, and the decision stays in the kernel's match beside Refused rather than moving into kernel/ps2. - The rate issue's resampler figures were round 1's six points, and "at least 135 dB" was false of its own log (134.6 dB at 100 Hz). They are now the sweep from every client rate in common use to both device rates, on rubato's AVX interpolator, linked at its evidence commit. Its exit names the three bounds A5 cites and the margin the owner signs. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015xhaydXCVRNscoccHYFUWy
#885 put the owner's standing ruling in the role prompts: a design its hardware's manufacturers or the published state of the art back follows and cites them, and its bench numbers are reported, never block it. This round's design is reviewed against them. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015xhaydXCVRNscoccHYFUWy
Design round 2: each finding of the round-1 review and its answer, at head
|
|
Owner's sign-off, recorded by the orchestrator. He was asked whether resampler errors held 125 dB below full scale (32.7 dB under the dithered 16-bit wire's own noise, SoX's 16-bit mastering level) meet his rule never to degrade audible quality. He chose "Yes, sign off". He will also run this round through ChatGPT; its reply is triaged before the design is accepted. |
Design review, round 2: head
|
…top's design branch #871 makes CR4.OSXSAVE required and gives user programs AVX state in XCR0, so std's feature detection reports AVX and FMA on a CPU that has them, and rubato's own dispatch takes AvxInterpolator on the T14 and the AMD bench. Round 3 of the design measures the resampler on that and on SseInterpolator, which rubato takes on an AVX CPU without FMA. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015xhaydXCVRNscoccHYFUWy
… take, as #877's third design round has it rubato picks its interpolator at construction from the CPU: AVX with FMA, else SSE3, on x86-64, and NEON on aarch64. Since #871 the T14 and the AMD bench take AVX, and an AVX CPU without FMA takes SSE; the exit now asks the bounds of each, not of whichever one the test host's own dispatch happens to take. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015xhaydXCVRNscoccHYFUWy
Design round 3: each finding of the round-2 review and its answer, at head
|
Design review, round 3: head
|
…runs on can take, as #877's fourth design round has it rubato 0.16.2's make_interpolator also falls back to ScalarInterpolator on both architectures, and no CPU ToyOS runs on reaches it: the kernel requires AVX state in XCR0 (kernel/pure/xsave.rs, REQUIRED), which every AVX CPU pairs with SSE3, and the aarch64 target enables NEON. The exit now names the set the design's host test builds, not every interpolator the crate contains. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015xhaydXCVRNscoccHYFUWy
Design round 4: each finding of the round-3 review and its answer, at head
|
Design review, round 4: head
|
|
Design accepted at
B8's departure stands: the bind takes no memory, and the pools, the domain and the descriptor list are taken once at boot. Build it. |
Design round 4. Nothing is built. This is the revised design and roast for A2 to A6 of the AMD bench's desktop, answering the round-3 review (issuecomment-6130503033). A1, AML reading firmware MMIO, is #875's S2 and not here.
Each item below is its own pull request, built only once this design is accepted in a comment here. The branch carries:
origin/main: A design follows what its hardware's manufacturers or the published state of the art back, and a bench verdict never blocks it #885's role prompts, and User FP/vector state is saved only at a switch, the preempt count drops lock, and the build refuses stray vector instructions #871, LAN stage D and B: netstack wakes only on a change, and the I219 takes a 1,000-descriptor ring at a fixed 131 µs throttle #861 and issues: an image's GUIDs are drawn from the host's random source #881.git diff --shortstat origin/main...HEAD: 2 files changed, 71 insertions, both new issues. Production and test lines: 0.What this was read from:
mainatab655a115. The orchestrator may ask the owner whether ChatGPT reviews a design pull request, and a reviewer triages what he returns #888, which landed since, changes only.claude/agents/orchestrator.mdand is not merged here;main;ToyOSOrg/evidencepr-877(A5), every one linked at its commit.The owner's rulings this design follows:
What a converter offering 48 kHz beside other rates but not 44.1 kHz does, and what one offering neither does, are this design's, not his.
Order
M1. The AMD bench's two codec graphs, as fixtures
lib/hda/fixtures' line format.build/sourcegate.rsrefuses, netstack'sMACline among them.lib/hda/fixtures/gets one file per controller, cut from those lines, with no subsystem ID.Why a boot: the demo's log prints the analog codec decoded, not as the words the codec sent, and the GPU's codec only in part. The fixtures exist so that every word in them is one a real machine sent (
lib/hda/src/fixture.rs). A4, A5 and A6a all test against these.A2. A keyboard that acks the set query and never answers is decided by the translate bit
Issue:
issues/the-amd-benchs-keyboard-acks-the-scancode-set-query-and-never-answers.md, filed here.Design. All of it is in
kernel/src/arch/x86_64/i8042/mod.rs.SetQuerygainsUnanswered: both bytes of0xF0 0x00were acked, and no set byte came within the wait below.Silentkeeps the exchange that stopped before both acks: the controller never took a write, or an ack never came.Unansweredarm besideRefused, decided asRefusedis:(assumed, the set query went unanswered);Unanswereddiffers fromSilent:Refusedcarries too (the T14 answers0xEE).0x00is the ack followed by the set byte (Select Alternate Scan Codes, p. 23), and the reference bounds the keyboard's response by 20 ms. The controller may inhibit the keyboard until its buffer is read (p. 38), so the wait starts at the kernel's read of the ack, later than the option byte the 20 ms runs from.0xF4keeps the stage's remainder. Today the set byte's wait spends the whole 750 ms stage.0xF4's read then expires at once, and the keyboard is disabled.Roast.
Unansweredtypes on an inference, asRefuseddoes, and the read-back exists to avoid exactly that. A keyboard whose wire is raw set 2, behind a firmware bit that says translate, would type nonsense.E0 30andE0 2E. Those are set 1's codes, so the wire is set 1.mainand is disabled after A2. Its late byte is read as0xF4's answer, andport_commandnames it (kbd cmd 0xf4 answered Some(0x41), not ack).0x60answers late are firmware emulations, an embedded controller or SMM trapping for USB legacy (i8042/mod.rs's self-test stage), not the device IBM timed.Told(0x41)is read on every boot of the suite, which runs under the new wait.Refused. Nothing moves intokernel/ps2.Checks.
Refused. Sorting an exchange intoSilentorUnansweredis the kernel's port I/O, which no host test reaches.i8042: kbd set2+xlat (assumed, the set query went unanswered) scanning on, GSI 1 … on.kbd DISABLED - the 0xF0 0x00 set query did not complete.Refusedline reads as onmain. This is the control.E0 30andE0 2Eunder the same assumption; IBM's reference for the wait.Told(0x41)), so the whole suite runs.A3. PS/2 Mute, Volume Down and Volume Up decode to their HID usages
Issue: the volume keys bullet of
issues/hda-has-no-jack-detection-volume-or-keys.md.Design.
SET1_E0entries:E0 20→0x7F, Mute;E0 2E→0x81, Volume Down;E0 30→0x80, Volume Up.Roast.
0xE2Mute,0xEAVolume Down,0xE9Volume Up.0x7F,0x81and0x80.RawKeyEvent::keycode,sdk/abi/src/input.rs). Carrying the Consumer page would add a page to every key event, an ABI change every reader of a key takes, for three keys the Keyboard page already names.E0 20was not seen on the bench. The volume run recorded onlyE0 30andE0 2E. Whether the bench's mute key comes over the i8042 at all, or through the embedded controller as an ACPI event, is unread.Checks.
kernel/ps2/tests/decode.rs's range test admits the three usages, without which it reds on them. No per-key test: three table entries are read against the specification.volumeupandaudiomute, which reach the compositor only through these entries. Negative control: A3's revert turns that test red.E0 30andE0 2E.A4. soundserver chooses the HDA controller, and the kernel binds the one it is told
Issue:
issues/the-amd-bench-answers-on-two-hda-controllers-and-plays-on-the-null-sink.md. It stays open after A4, and A5 meets its exit.Design.
At boot the kernel lists every controller it can bind, takes the stream's memory once, and binds none.
kernel/src/drivers/hda.rsprobes every class-0403 function as it does now: power, memory space, reset, thenSTATESTS.initrefuses one today, and is not listed.INTCTLclear, so it raises nothing.pcidev::note_kernel_driver), the one never bound included: its registers are the kernel's to serve from boot, and apci:claim on it is refusedKernelDriven.Absent, as today.inittakes the stream's memory once, as it does today: a freshDeviceSpace, the descriptor-list and PCM pools in it, and the descriptor list written.DmaPoolcaller stays at boot, before any process exists: virtio's, xHCI's, and this one.DmaPool::leak), since every claim's PCM object maps the PCM pool.The
hda-audioclaim describes the stream and the list. As today it carries the PCM handle, the period shape and the tag. For each listed controller it gives itsSTATESTS, its output stream's offset, and its PCI address for the lines that name it.The register calls' offset word names the controller as well as the register (
toyos_abi::hda::Reg). It is decoded once at the boundary, and an index past the claim's current list is refused.A new call,
SYS_HDA_BIND(claim, controller), binds the controller it names. It takes no memory, and answers only its result, since the claim already describes the stream. Its body:DeviceSpace. Neither unit allocates there: VT-d rewrites the context entryiommu::initgave every enumerated function (vtd/table.rs,bind), and SMMUv3 writes the function's stream table entry. Where nothing translates, as on the AMD bench, there is nothing to attach;SETTLE_NS, and programs it: the descriptor list's address and length, the last valid index, the tag and the interrupt enables;ISR.stream, then starts bus mastering (start_bus_mastering) and setsINTCTL;GCTL.CRSTclear, read back, bounded bySETTLE_NS). One that never reads back is named; nothing reaches it again either way.The body's one device failure is the stream reset's settle. On it, every listed controller, the chosen one included, has its message turned off and goes back into reset, and the state becomes
Refused.One state, under
CONTROLLER, decides every call.CONTROLLERholds one of:Listed(controllers), the boot's list beside the stream's memory. The register calls reachICS,ICWandIRRon any listed controller.Binding. One bind owns every listed controller. Every register call, and every other bind, is refused by name (WouldBlock), and nothing waits for it. A claim answersOwned: the binder's frame holds the claim until the bind returns.Bound(controller). The register calls reach the bound controller as they do today. A bind naming it answers success from the state.Refused. The body failed on the device. Every register call and bind is refused (Io) for the rest of the boot, and the log names the failure, asinit's refusals do today.Unusable, which the syscall returns asNotSupported. The controller is on the machine and could not be handed over, which is what that variant says, and the kernel'shda:line says why.refused,system/supervisor/src/main.rs) nameshda:besidepcidev:,partclaim:,isa:andacpi:.Absent: that tells the supervisor the machine has no such device, a configuration rather than a fault.INFO's own lock goes and no reader sees a list and a binding that disagree.The transition is one-shot:
Listed→Binding→BoundorRefused, and nothing returns toListed.SYS_HDA_BINDtakesCONTROLLER. FromListed, with the index inside the list, it moves the list into its own frame and leavesBinding; an index past the list is refused and the state stays. It gives the lock back.CRSTsettle.CONTROLLERagain only to storeBoundorRefused, gives it back, and returns.No device wait sits under
CONTROLLER, and the bind copies nothing to the caller. The register calls hold it for one register access, as today.The bind takes no memory, so no allocation of its can be refused. The domain, the pools and the descriptor list are
init's, and so is each message: the body writes registers, configuration space and one entry of the unit's own tables.ISR.stream's one writer is the bind that leftListed, before bus mastering andINTCTLlet its controller raise the message. No state returns toListed, so there is no second writer, and itsSAFETYcomment says so.A bind cannot strand
Binding. The body's waits are spins, and a killed thread leaves at its next return to user (kernel/src/scheduler.rs), so the body always ends inBoundorRefused.After the bind, the list is the bound controller alone, at index 0. The register word indexes the claim's current list, so the binder and a later claim both name it 0, and any other index is refused past the list. A later claim, after soundserver restarts, describes that one controller, and binding it again answers success.
soundserver chooses.
Hda::claimwalks every listed controller's codecs through its ownsend, before it starts any thread.lib/hdagainschoose. Over each controller's codecs, it returns the one controller whose graph reaches an output (find_output_path).The module docs follow.
hda.rs's "Codec and pin decisions belong to soundserver" gains the controller.HdaInfo's andHdaDev's docs describe the list and the bind.Roast.
New ABI:
The HDA stage of
issues/every-driver-is-still-in-the-kernel.mdretires thehda-audioclass, and all of this with it.The stream's memory is taken at boot, not at the bind. The round-3 review named the other way: the bind takes its pools fallibly and refuses
OutOfMemory. That would not make the bind fallible.DeviceSpaceand its mapping grow the unit's tables, and that growth panics when memory is out: VT-d'sTables::alloc(vtd/table.rs:53-54) and SMMUv3'salloc(smmu/mod.rs:190). Both units would have to refuse instead.vtd/domain.rs, whoselive"never shrinks"). A claim holder retrying under memory pressure would spend them.init, the memory is boot's, as every other driver's pools are. The bind is then left nothing to refuse, and a loser holds nothing to drop.maintakes the same on a machine it binds. On the AMD bench, whichmainrefuses before allocating, it is 4 MiB more.Every listed controller's message is armed at boot. With interrupt remapping that is one VT-d remapping entry per listed controller, never released (
vtd/interrupt.rs,allocate): at most four, wheremainspends one. The AMD bench's AMD-Vi programs no unit, so it spends none. Arming at boot takes the MSI-X table window's mapping, and the arming's own refusals, out of the bind.An index in the register word, not a device object per controller. A handle per controller would carry the index with no word for it, since the register calls already resolve the claimed handle (
kernel/src/syscall/device.rs). But it needs one of two things:object/ops.rshas to answer.The index costs one decode in
toyos-abiand one bound check.Renumbering to 0. A thread of the claim holder that kept a pre-bind index other than 0 is refused past the list. One that kept 0 for another controller reaches the bound one, whose registers the claim holds either way. soundserver binds before it starts a thread.
A loser is refused, not queued. A second bind while one runs is the claim holder racing itself. Answering it after the first would add a wait that only a caller with a bug reaches.
The kernel binds at a syscall, not at boot. The bind's settle waits run on soundserver's thread and are charged to it, bounded by the same
SETTLE_NS.Until soundserver binds, every listed controller stays out of reset with its link up. On
mainthe AMD bench keeps both out of reset too, refused. On a one-controller machine the bind comes at soundserver's start instead of at boot.A refused bind outlasts soundserver. After
Refused, the supervisor refuses soundserver's restart: the claim answersUnusable, and a restart that cannot mint a claim the process before it held is refused (Served::Restart).mainthe same device failure isinit's, before any claim, and soundserver presents the null sink across restarts.soundserver walks a controller it will not use. At every soundserver start, the GPU's codec on the AMD bench is walked: one more codec's read verbs, before any client is served.
A machine with two controllers that each reach a speaker, headphone or line-out gets no HDA audio, refused by name.
Checks.
Host:
chooseover:The one-shot is the type's:
initalone buildsListed, and the bind'sListedarm alone takes the list out of it, both read in the diff. That the bind takes no memory is read in the diff too: its body calls no allocator. No host test reaches the kernel'sLock.Metal, AMD bench: the boot lists both controllers and takes the stream's memory once. soundserver walks both, binds the analog one, and names the other. Until A5, it refuses the 48 kHz-only converter by name.
Metal, T14:
hda_tone,hda_client_stall,audio_idle_suspend,shipped_client_departuresandsoundserver_log_stallstay green. This is the control.Oracle: the codecs' own answers on metal, decoded per the HD Audio specification. The GPU codec's pins read Digital Other Out on the bench.
QEMU: no guest profile has an HDA controller (
git grep intel-hdaovertests/andbuild/finds nothing), so no guest test reaches the choice. The whole suite still runs, since every boot passes throughhda::initwith no controller.A5. HDA runs at a rate its converter offers, and cpal takes the rate soundserver answers
Issues:
issues/hda-plays-only-at-44100-hz-and-the-amd-benchs-converter-offers-48000-alone.md, filed here;issues/cpal-backend-hardcodes-the-format.md;The device rate.
[44_100, 48_000], intoyos-mixer.choosereads it too, instead of its own copy of the same order.lib/hda::config::format(codecs, path, rate)builds the format for a given rate. soundserver picks the first declared rate the converter's own PCM word offers at 16 bits. All three machines' converters set Format Override, so each answers its own word.Refusal::Ratenames the rates it offers.run_hdaruns at the chosen rate.The resampler, held to the dithered 16-bit wire by published practice.
The wire's own noise. soundserver quantizes every period with TPDF dither of ±1 LSB (
system/soundserver/mixer/src/format.rs).Three bounds, each cited.
rateeffect at its "high" quality, which its manual gives for "16-bit mastering (use with dither)". Its "Rej dB" column is "the level of noise rejection". It is the published figure for this wire.The parameters, per stream, from its two rates:
rubato::calculate_cutoff(512, BlackmanHarris2)= 0.9734.asynchro_sinc.rs,make_interpolator). So a fixed length widens the transition, against the output's Nyquist, by the ratio. Lengthening the sinc by the ratio gives the 512-frame filter's response, relative to the lower rate, at every ratio.Which interpolator runs. rubato 0.16.2 picks one when a resampler is built (
make_interpolator,asynchro_sinc.rs:145-189). On x86-64 it takesAvxInterpolatorwhere std reports AVX and FMA, elseSseInterpolatorwhere it reports SSE3. On aarch64 it takesNeonInterpolator.CR4.OSXSAVEis inCR4_REQUIRED(kernel/src/arch/x86_64/control_regs.rs), andXCR0holds AVX state on every CPU the kernel runs (kernel/pure/xsave.rs,REQUIRED). std's detection readsOSXSAVEandXGETBVbefore it reports AVX or FMA (rust/library/std_detect/src/detect/os/x86.rs).AvxInterpolator: its leaf-1ECX,0x7ffafbbf(kernel/cpuvuln/fixtures/t14/cpuid.txt), sets FMA (bit 12) and AVX (bit 28). The AMD bench's Ryzen 7 4800U is Zen 2, which implements both.SseInterpolatoris what an x86-64 CPU with AVX and without FMA takes, and the kernel does not refuse such a CPU.ScalarInterpolator, is taken by no CPU ToyOS runs on. x86-64 requires AVX (kernel/pure/xsave.rs,REQUIRED), and every CPU with AVX has SSE3. The aarch64 target compiles NEON in:rustc --print cfg --target aarch64-unknown-toyosliststarget_feature="neon".CR4.OSXSAVEwas clear and every x86-64 machine took SSE.Measured on all three interpolators, each built explicitly as the host test builds it:
SincFixedOut::new_with_interpolatorover the interpolator constructed with the sinc length and cutoffmake_interpolatorderives.ROSETTA_ADVERTISE_AVX=1. NEON ran on the arm64 dev host. Each run prints the CPU's features and what rubato's own dispatch takes.SincFixedOut::newin the same process, all 110 configuration-pairs are bit-identical on each of the three (a5r3-probe-sse.log, -avx, -neon).Worst cases on
SseInterpolator(a5r3-sweep-sse.log, its summary at the end):AvxInterpolator(a5r3-sweep-avx.log), and +0.00010 dB, 127.4 dB and 130.2 dB onNeonInterpolator(a5r3-sweep-neon.log).Cost. Per output frame and channel, the cubic interpolator takes four dot products of the sinc's length: 2,048 multiply-adds at 512, and 8,928 for a 192 kHz client on a 44.1 kHz device, whose sinc is 2,232.
SseInterpolator, the least of five 2 s trials (a5r3-cost-sse.log): 44.8 µs per 2.67 ms period from 44.1 to 48 kHz, and 391.8 µs per 2.90 ms period from 192 to 44.1 kHz. Today's set takes 13.0 µs from 44.1 to 48 kHz.Protocol (
sdk/toyos/src/audio.rs):MSG_DEVICE_DESCRIBE. It gets one answer bytry_send, and is closed.StreamOpenResponsegains the fade's frames, so a client can derive how long soundserver may take to let go of a stream.The cpal fork, branch
toyos-0.18.0, gets one appended commit. Every lockfile that names the branch is bumped in the same pull request.default_output_configis the device's own: its rate and channels, I16, its period.supported_output_configsis mono and stereo, I16, over the accepted rate range. A stream at any of them builds, and soundserver resamples it.RELEASE_WITHINis derived from the stream's slot count, its fade and its period.Roast.
make_interpolatordoes, since rubato does not export that function. The fourth test below turns red if a rubato bump changes either, or adds an interpolator the list lacks.default_output_configbefore any stream exists. Opening a stream to learn the rate would cost a fade and a ring.MSG_INSPECT's snapshot already answers the device's rate, channels and period, on the same port, by the same singletry_sendand close (system/soundserver/src/inspect.rs,control.rs).inspect's key/value schema for a reader that prints it: a key renamed forinspectwould break every cpal client, cpal would take a parser of a diagnostic format, and the snapshot carries no accepted rate range.Checks.
formatover the T14, QEMU and AMD fixtures.cargo run -- --ci hostruns on CI's x86-64 runner and on an arm64 host.SincFixedOut::newwith the ratio and the shapeopen_streampasses today (system/soundserver/src/client.rs).open_streamand the tests make the same call, so the ratio and that construction are under test too.SseInterpolatorandAvxInterpolatoron x86-64,NeonInterpolatoron aarch64. Each comes from the same parameters, with the sinc length and cutoffmake_interpolatorderives, throughSincFixedOut::new_with_interpolatorat the same ratio, period and channels.target_arch.open_streamruns, is bit-identical to one of the explicit builds at every pair, so the three claims hold on the resampler soundserver runs.make_interpolator's cutoff scaling (a5r3-no-cutoff-scaling.patch): the fourth test.ROSETTA_ADVERTISE_AVX=1, and NEON natively; each log's first line names the CPU's features and the interpolator rubato's dispatch takes. Every exit code is in a5r4-control-runs.log, from a5r4-control.sh.ready … 48000Hz.hda_tone,hda_client_stall(the two-controller issue's exit),audio_idle_suspendandshipped_client_departuresare green.ready … 44100Hz, and its audio rows are green.0x000e0040on the AMD bench,0x000e0060on the T14;A6. Master level and mute at the codec, the volume keys and the overlay, as two pull requests
Issues:
issues/hda-has-no-jack-detection-volume-or-keys.md: master volume and mute, and the volume keys;issues/toyos-has-a-desktop.md, stage 8.A6a. soundserver: the master at the codec
Design.
lib/hda::config::master(path, setting)gives the verbs for a level and mute, and decodes their readback.issues/the-kernel-keeps-nothing-it-enumerates.mdlands.volume.images/system.tomlgives it to the compositor and to nothing else, and asoundserverconnection cannot reach it.MSG_VOLUME_STEP { delta }andMSG_VOLUME_MUTE.GET_AMP_GAIN_MUTEafter each set, never the intent. It is sent by onetry_send.unavailable, by name. No mixer gain stands in for a master.Roast.
unavailable. A virtio-sound device that offeredVIRTIO_SND_F_CTLScould carry a master. None in reach offers it; this is to be read off one QEMU boot's feature bits.Checks.
Host:
master's verbs over the T14, AMD and QEMU fixtures. Gain goes on the converter and mute on both pins; on QEMU's codec, both go on the converter. A path with neither is refused.unavailableincluded.Metal, T14 and AMD bench: a job holding
volume:Negative control: the revert refuses the job its port.
Oracle:
QEMU: the whole suite.
A6b. The compositor: the keys and the overlay
Design.
toyos-desktop'skey_actionmakes0x7F,0x80and0x81the desktop's. A press isVolume(Mute | Up | Down). Its release is swallowed, since no window saw the press.kernel/ps2/tests/decode.rs's list of the usages the rest of the tree names gains the three, since the compositor then keys off them.volumeon its first press.try_send, and adds up the presses that arrive meanwhile.FrameRx.toyos-desktop.Roast.
Checks.
key_actionfor the three usages: a press acts, its release is swallowed, and a prompt takes them. Negative control: reverting the three arms, so the usages fall to the focused window, turns it red.volumeupandaudiomutethrough QMP'sinput-send-event. Screendumps then show the overlay drawn in the rectangletoyos-desktopcomputes, and then removed, each waited for under a hang ceiling.unavailableanswer. That is what the test asserts.Unsure
INTCTLclear. The AMD bench's boot, which lists two, is the first reading of it.AvxInterpolatorrests on AMD's Zen 2 having FMA. Its own CPUID word is not in the tree.mainasks the converter itself either way. No machine in reach has such a converter, and this design does not build the inheritance.Issues filed here
issues/the-amd-benchs-keyboard-acks-the-scancode-set-query-and-never-answers.md(A2);issues/hda-plays-only-at-44100-hz-and-the-amd-benchs-converter-offers-48000-alone.md(A5).Round 2 dropped the keyboard issue's host-test exit, and the move into
kernel/ps2from its owner line. It corrected the rate issue's resampler figures to the sweep, and its exit to the three bounds and the owner's margin. Round 3 widened that exit's host test to every interpolator rubato can take. Round 4 words it as the set the design tests: every interpolator rubato can take on a CPU ToyOS runs on.The orchestrator's survey found other needs with no issue. They are outside this brief and are not filed here: a BAR outside its bridge's window, netstack's cards and its Wi-Fi control, an early panic on a CPU that states no counter rate, and the AMD bench's touchpad.
Gates
This is a design round with no code. The gates it ran:
cargo run -- --ci hostatdc0d0bef2:EXIT=0, "Host: 76 step(s), all green" at line 8808 (ci-host-dc0d0bef2.log, masked; its exit code in ci-host-dc0d0bef2.runs.log). It ran from 19:04:41Z to 19:08:13Z, after the head was committed at 19:04:35Z.build/sourcegate.rsand the issue checks read the two issue files.cargo build --releasefor both architectures.EXIT=0; the three unpatched probesEXIT=0; and the three patched probesEXIT=1(a5r4-control-runs.log).🤖 Generated with Claude Code
https://claude.ai/code/session_015xhaydXCVRNscoccHYFUWy