redo boot around an explicit system volume and fixed kernel/HAL images, redo volumes and filesystem paths around capabilities instead of drive numbers and kernel CWD state, add a capability/security model with derived and revocable handles and security contexts, add port IPC and rssrv to manage the userspace resource namespace and publish the system volume, move process, dll and path loading to userspace and add process builder syscalls, init now supervises rssrv and the session process, redo the syscall ABI around request structs and four arguments, add a volume manager and proper partition arrival/removal handling so FAT and NTFS mount dynamically, clean up the HAL/DDK boundary so drivers don't depend on HAL internals, save fpu state properly now, the serial driver doesn't hang on a missing port, fix AHCI startup races, fix timeout accounting, fix shared mmap writeback, more smoke tests

This commit is contained in:
maksw committed 2026-08-20 12:33:17 +02:00
1 parent 4add6789ba
commit f882d339fb
232 files changed
+20934 -8898

No files matched your search

+23 -391
View File
@@ -8,6 +8,7 @@
#include <ntlite/ddi/io_driver.h>
#include <ntlite/ddk/audio.h>
#include <kernel/ke_audio.h>
#include <kernel/ke_id.h>
#include <kernel/ke_debug.h>
#include <kernel/ke_event.h>
#include <kernel/ke_list.h>
@@ -22,7 +23,6 @@
#define KE_AUDIO_ENDPOINT_TAG MM_POOL_TAG('a', 'e', 'p', 't')
#define KE_AUDIO_RING_TAG MM_POOL_TAG('a', 'r', 'n', 'g')
#define KE_AUDIO_SELFTEST_TAG MM_POOL_TAG('a', 't', 's', 't')
#define KE_AUDIO_PERIOD_STATE_FREE 0u
#define KE_AUDIO_PERIOD_STATE_FILLING 1u
@@ -31,7 +31,6 @@
#define KE_AUDIO_PERIOD_STATE_REAPING 4u
#define KE_AUDIO_TICKS_PER_MILLISECOND 1000ull
#define KE_AUDIO_SELFTEST_WAIT_MILLISECONDS 5000ull
typedef struct KE_AUDIO_PERIOD_CONTRIBUTION {
KE_AUDIO_STREAM* Stream;
@@ -103,7 +102,7 @@ struct IO_AUDIO_ENDPOINT {
EVENT* MixerExitEvent;
THREAD* MixerThread;
SPINLOCK NotifyLock;
uint64_t EndpointId;
uint32_t EndpointId;
IO_AUDIO_ENDPOINT_KIND Kind;
KE_AUDIO_ENDPOINT_STATE State;
uint32_t Capabilities;
@@ -174,8 +173,8 @@ typedef struct KE_AUDIO_LIFECYCLE_SNAPSHOT {
static SPINLOCK gAudioRegistryLock = SPINLOCK_INIT;
static LIST_ENTRY gAudioEndpointList;
static uint32_t gAudioEndpointCount;
static uint64_t gAudioNextEndpointId = 1;
static uint64_t gAudioDefaultEndpointId;
static KE_ID_ALLOCATOR gAudioEndpointIds = KE_ID_ALLOCATOR_INIT(1u);
static uint32_t gAudioDefaultEndpointId;
static uint8_t gAudioInitialized;
static KE_AUDIO_CORE_STATS gAudioCoreStats;
@@ -433,7 +432,7 @@ static uint32_t KiAudioEndpointRank(IO_AUDIO_ENDPOINT_KIND kind) {
// Recomputes the default endpoint while the registry lock is held.
static void KiAudioSelectDefaultEndpointLocked(void) {
uint64_t selectedId = 0;
uint32_t selectedId = 0;
uint32_t selectedRank = UINT32_MAX;
for (LIST_ENTRY* link = gAudioEndpointList.Fwd;
link != &gAudioEndpointList;
@@ -452,7 +451,7 @@ static void KiAudioSelectDefaultEndpointLocked(void) {
}
// References one ready endpoint by stable identifier.
static IO_AUDIO_ENDPOINT* KiAudioReferenceEndpointById(uint64_t endpointId) {
static IO_AUDIO_ENDPOINT* KiAudioReferenceEndpointById(uint32_t endpointId) {
IO_AUDIO_ENDPOINT* result = (IO_AUDIO_ENDPOINT*)0;
uintptr_t flags = KeAcquireSpinlock(&gAudioRegistryLock);
for (LIST_ENTRY* link = gAudioEndpointList.Fwd;
@@ -1421,7 +1420,18 @@ static KSTATUS KiAudioRegisterEndpoint(const IO_AUDIO_ENDPOINT_REGISTRATION* reg
ObDereferenceObject(&endpoint->Header);
return NTLSTATUS_NO_MEMORY;
}
endpoint->EndpointId = gAudioNextEndpointId++;
KSTATUS idStatus = KeAllocateId32(&gAudioEndpointIds, &endpoint->EndpointId);
if (!KSUCCESS(idStatus)) {
KiAudioSetEndpointStateLocked(endpoint, KeAudioEndpointStopping);
endpoint->FailureStatus = idStatus;
KeReleaseSpinlock(&gAudioRegistryLock, flags);
KeSignalEvent(endpoint->WorkEvent);
(void)KeWaitForEvent(endpoint->MixerExitEvent, 0);
ObDereferenceObject(&endpoint->MixerThread->Header);
endpoint->MixerThread = (THREAD*)0;
ObDereferenceObject(&endpoint->Header);
return idStatus;
}
KiAudioSetEndpointStateLocked(endpoint, KeAudioEndpointReady);
endpoint->Registered = 1;
ObReferenceObject(&endpoint->Header);
@@ -1590,9 +1600,9 @@ const NTL_DDK_AUDIO* KeAudioGetDdk(void) {
}
// Returns the current default endpoint identifier.
uint64_t KeAudioGetDefaultEndpointId(void) {
uint32_t KeAudioGetDefaultEndpointId(void) {
uintptr_t flags = KeAcquireSpinlock(&gAudioRegistryLock);
uint64_t endpointId = gAudioDefaultEndpointId;
uint32_t endpointId = gAudioDefaultEndpointId;
KeReleaseSpinlock(&gAudioRegistryLock, flags);
return endpointId;
}
@@ -1606,7 +1616,7 @@ KSTATUS KeAudioQueryEndpoints(KE_AUDIO_ENDPOINT_INFO* endpoints,
IO_AUDIO_ENDPOINT* references[KE_AUDIO_MAX_ENDPOINTS];
uint32_t count = 0;
uint64_t defaultId = 0;
uint32_t defaultId = 0;
uintptr_t flags = KeAcquireSpinlock(&gAudioRegistryLock);
defaultId = gAudioDefaultEndpointId;
for (LIST_ENTRY* link = gAudioEndpointList.Fwd;
@@ -1668,7 +1678,7 @@ KSTATUS KeAudioQueryEndpoints(KE_AUDIO_ENDPOINT_INFO* endpoints,
}
// Creates one logical render stream with a fixed-capacity source ring.
KSTATUS KeAudioCreateStream(uint64_t endpointId,
KSTATUS KeAudioCreateStream(uint32_t endpointId,
const IO_AUDIO_FORMAT* format,
KE_AUDIO_STREAM** outStream) {
if (!outStream || !KiAudioValidateSourceFormat(format))
@@ -2010,7 +2020,7 @@ KSTATUS KeAudioSetStreamVolume(KE_AUDIO_STREAM* stream,
}
// Updates endpoint master software gain and separate logical mute state.
KSTATUS KeAudioSetMasterVolume(uint64_t endpointId, float volume, bool muted) {
KSTATUS KeAudioSetMasterVolume(uint32_t endpointId, float volume, bool muted) {
if (!KiAudioFloatIsFinite(volume) || volume < 0.0f || volume > 1.0f)
return NTLSTATUS_INVALID_PARAMETER;
IO_AUDIO_ENDPOINT* endpoint = KiAudioReferenceEndpointById(endpointId);
@@ -2080,381 +2090,3 @@ KSTATUS KeAudioQueryStream(KE_AUDIO_STREAM* stream, KE_AUDIO_STREAM_INFO* infoOu
KiAudioReleaseMutex(stream->Lock);
return NTLSTATUS_SUCCESS;
}
// Copies one endpoint snapshot by stable identifier.
static KSTATUS KiAudioSelfTestQueryEndpoint(uint64_t endpointId,
KE_AUDIO_ENDPOINT_INFO* infoOut) {
KE_AUDIO_ENDPOINT_INFO infos[KE_AUDIO_MAX_ENDPOINTS];
uint32_t count = 0;
KSTATUS status = KeAudioQueryEndpoints(infos, KE_AUDIO_MAX_ENDPOINTS, &count);
if (KFAILED(status))
return status;
for (uint32_t index = 0; index < count; index++) {
if (infos[index].EndpointId == endpointId) {
*infoOut = infos[index];
return NTLSTATUS_SUCCESS;
}
}
return NTLSTATUS_NOT_FOUND;
}
// Generates one bounded run of a ramped 440 Hz stereo sine wave.
static void KiAudioSelfTestGenerateTone(int16_t* frames,
uint32_t frameCount,
uint64_t firstFrame,
double* sineInOut,
double* cosineInOut) {
const uint64_t totalFrames = 3ull * KE_AUDIO_OUTPUT_SAMPLE_RATE;
const uint64_t rampFrames = 384ull;
const double amplitude = 8231.0;
const double sineStep = 0.057564026959567284;
const double cosineStep = 0.9983418166140283;
double sine = *sineInOut;
double cosine = *cosineInOut;
for (uint32_t index = 0; index < frameCount; index++) {
uint64_t frame = firstFrame + index;
uint64_t framesFromEnd = totalFrames - 1ull - frame;
double envelope = 1.0;
if (frame < rampFrames)
envelope = (double)frame / (double)(rampFrames - 1ull);
if (framesFromEnd < rampFrames) {
double fadeOut = (double)framesFromEnd / (double)(rampFrames - 1ull);
if (fadeOut < envelope)
envelope = fadeOut;
}
double scaled = sine * amplitude * envelope;
int32_t sample = scaled >= 0.0 ? (int32_t)(scaled + 0.5)
: (int32_t)(scaled - 0.5);
frames[index * 2u] = (int16_t)sample;
frames[index * 2u + 1u] = (int16_t)sample;
double nextSine = sine * cosineStep + cosine * sineStep;
double nextCosine = cosine * cosineStep - sine * sineStep;
sine = nextSine;
cosine = nextCosine;
}
*sineInOut = sine;
*cosineInOut = cosine;
}
// Waits for one selftest stream condition with a finite boot-time deadline.
static KSTATUS KiAudioSelfTestWait(KE_AUDIO_STREAM* stream) {
EVENT* event = KeAudioStreamWaitEvent(stream);
if (!event)
return NTLSTATUS_OBJECT_DEAD;
uint32_t selected = 0;
return KeWaitForMultipleEvents(&event,
1,
0,
KE_AUDIO_SELFTEST_WAIT_MILLISECONDS,
&selected);
}
// Writes one generated run while using the stream event for bounded backpressure.
static KSTATUS KiAudioSelfTestWriteFrames(KE_AUDIO_STREAM* stream,
const int16_t* frames,
uint32_t frameCount,
uint64_t expectedDiscontinuity) {
uint32_t offset = 0;
while (offset < frameCount) {
uint32_t written = 0;
KSTATUS status = KeAudioWriteStream(stream,
frames + offset * 2u,
frameCount - offset,
&written);
if (KSUCCESS(status) && written) {
offset += written;
continue;
}
if (status != NTLSTATUS_WOULD_BLOCK)
return KFAILED(status) ? status : NTLSTATUS_FAILURE;
KE_AUDIO_STREAM_INFO info;
status = KeAudioQueryStream(stream, &info);
if (KFAILED(status))
return status;
if (info.State == KeAudioStreamFailed)
return KFAILED(info.FailureStatus) ? info.FailureStatus : NTLSTATUS_DEVICE_ERROR;
if (info.DiscontinuityGeneration != expectedDiscontinuity)
return NTLSTATUS_DEVICE_ERROR;
KE_AUDIO_STREAM_WAIT_CONDITION condition = {
.Mask = KE_AUDIO_WAIT_WRITABLE | KE_AUDIO_WAIT_FAILED | KE_AUDIO_WAIT_DISCONTINUITY,
.WritableFrames = 1,
.DiscontinuityGeneration = expectedDiscontinuity,
};
status = KeAudioArmStreamWait(stream, &condition);
if (KFAILED(status))
return status;
status = KiAudioSelfTestWait(stream);
if (KFAILED(status) || status == NTLSTATUS_TIMEOUT)
return status;
}
return NTLSTATUS_SUCCESS;
}
// Prints the common endpoint and stream counters for one selftest outcome.
static void KiAudioSelfTestPrintCounters(uint64_t endpointId,
const KE_AUDIO_ENDPOINT_INFO* endpointBefore,
const KE_AUDIO_ENDPOINT_INFO* endpointAfter,
const KE_AUDIO_STREAM_INFO* streamInfo,
uint64_t expectedDiscontinuity) {
uint64_t mixedPeriods = endpointAfter->PeriodsMixed - endpointBefore->PeriodsMixed;
uint64_t completedPeriods = endpointAfter->PeriodsCompleted - endpointBefore->PeriodsCompleted;
uint64_t interruptCount = endpointAfter->InterruptCount - endpointBefore->InterruptCount;
uint64_t endpointUnderruns = endpointAfter->Underruns - endpointBefore->Underruns;
uint64_t endpointDiscontinuities = endpointAfter->DiscontinuityGeneration -
endpointBefore->DiscontinuityGeneration;
uint64_t positionFrames = endpointAfter->HardwarePositionFrames -
endpointBefore->HardwarePositionFrames;
uint64_t streamDiscontinuities = streamInfo->DiscontinuityGeneration >= expectedDiscontinuity
? streamInfo->DiscontinuityGeneration - expectedDiscontinuity
: 0;
DbgPrint("AUDIO final selftest: endpoint=%llu submitted=%llu consumed=%llu presented=%llu\n",
(unsigned long long)endpointId,
(unsigned long long)streamInfo->FramesSubmitted,
(unsigned long long)streamInfo->FramesConsumed,
(unsigned long long)streamInfo->FramesPresented);
DbgPrint("AUDIO final selftest: periods mixed=%llu completed=%llu interrupts=%llu\n",
(unsigned long long)mixedPeriods,
(unsigned long long)completedPeriods,
(unsigned long long)interruptCount);
DbgPrint("AUDIO final selftest: underruns endpoint=%llu stream=%llu discontinuities endpoint=%llu stream=%llu\n",
(unsigned long long)endpointUnderruns,
(unsigned long long)streamInfo->Underruns,
(unsigned long long)endpointDiscontinuities,
(unsigned long long)streamDiscontinuities);
DbgPrint("AUDIO final selftest: position start=%llu end=%llu delta=%llu\n",
(unsigned long long)endpointBefore->HardwarePositionFrames,
(unsigned long long)endpointAfter->HardwarePositionFrames,
(unsigned long long)positionFrames);
}
// Plays the final-path sine test through the selected hardware endpoint and mixer.
void KiRunAudioFinalPathSelfTest(void) {
const uint64_t totalFrames = 3ull * KE_AUDIO_OUTPUT_SAMPLE_RATE;
const uint32_t chunkFrames = 1024u;
const char* failurePhase = (const char*)0;
KSTATUS failureStatus = NTLSTATUS_SUCCESS;
uint64_t failureValue = 0;
uint64_t endpointId = KeAudioGetDefaultEndpointId();
KE_AUDIO_ENDPOINT_INFO endpointBefore;
KE_AUDIO_ENDPOINT_INFO endpointAfter;
KE_AUDIO_STREAM_INFO startInfo;
KE_AUDIO_STREAM_INFO streamAfter;
KE_AUDIO_STREAM* stream = (KE_AUDIO_STREAM*)0;
int16_t* chunk = (int16_t*)0;
uint64_t expectedDiscontinuity = 0;
int haveEndpointBefore = 0;
int haveEndpointAfter = 0;
int haveStreamAfter = 0;
memset(&endpointBefore, 0, sizeof(endpointBefore));
memset(&endpointAfter, 0, sizeof(endpointAfter));
memset(&startInfo, 0, sizeof(startInfo));
memset(&streamAfter, 0, sizeof(streamAfter));
if (!endpointId) {
DbgPrint("AUDIO final selftest: SKIP no default endpoint\n");
return;
}
KSTATUS status = KiAudioSelfTestQueryEndpoint(endpointId, &endpointBefore);
if (KFAILED(status) || !endpointBefore.Available ||
endpointBefore.State != KeAudioEndpointReady) {
failurePhase = "endpoint-ready";
failureStatus = KFAILED(status) ? status : NTLSTATUS_DEVICE_ERROR;
goto cleanup;
}
haveEndpointBefore = 1;
if (endpointBefore.HardwareFormat.SampleRate != KE_AUDIO_OUTPUT_SAMPLE_RATE ||
endpointBefore.HardwareFormat.ChannelCount != KE_AUDIO_OUTPUT_CHANNELS ||
endpointBefore.HardwareFormat.SampleFormat != IoAudioSampleS16) {
failurePhase = "endpoint-format";
failureStatus = NTLSTATUS_NOT_SUPPORTED;
failureValue = endpointBefore.HardwareFormat.SampleFormat;
goto cleanup;
}
DbgPrint("AUDIO final selftest: begin endpoint=%llu kind=%u format=48000/S16/stereo\n",
(unsigned long long)endpointId,
(unsigned)endpointBefore.Kind);
IO_AUDIO_FORMAT format = {
.SampleRate = KE_AUDIO_OUTPUT_SAMPLE_RATE,
.ChannelCount = KE_AUDIO_OUTPUT_CHANNELS,
.SampleFormat = IoAudioSampleS16,
};
status = KeAudioCreateStream(endpointId, &format, &stream);
if (KFAILED(status)) {
failurePhase = "stream-create";
failureStatus = status;
goto cleanup;
}
chunk = (int16_t*)MmAllocatePoolTag(
(size_t)chunkFrames * KE_AUDIO_OUTPUT_BYTES_PER_FRAME,
KE_AUDIO_SELFTEST_TAG);
if (!chunk) {
failurePhase = "tone-allocation";
failureStatus = NTLSTATUS_NO_MEMORY;
goto cleanup;
}
double sine = 0.0;
double cosine = 1.0;
uint64_t submitted = 0;
while (submitted < KE_AUDIO_STREAM_RING_FRAMES) {
uint32_t count = (uint32_t)(KE_AUDIO_STREAM_RING_FRAMES - submitted);
if (count > chunkFrames)
count = chunkFrames;
KiAudioSelfTestGenerateTone(chunk, count, submitted, &sine, &cosine);
uint32_t written = 0;
status = KeAudioWriteStream(stream, chunk, count, &written);
if (KFAILED(status) || written != count) {
failurePhase = "initial-prefill";
failureStatus = KFAILED(status) ? status : NTLSTATUS_FAILURE;
failureValue = written;
goto cleanup;
}
submitted += written;
}
status = KeAudioStartStream(stream);
if (KFAILED(status)) {
failurePhase = "stream-start";
failureStatus = status;
goto cleanup;
}
status = KeAudioQueryStream(stream, &startInfo);
if (KFAILED(status)) {
failurePhase = "start-query";
failureStatus = status;
goto cleanup;
}
expectedDiscontinuity = startInfo.DiscontinuityGeneration;
while (submitted < totalFrames) {
uint64_t remaining = totalFrames - submitted;
uint32_t count = remaining < chunkFrames ? (uint32_t)remaining : chunkFrames;
KiAudioSelfTestGenerateTone(chunk, count, submitted, &sine, &cosine);
status = KiAudioSelfTestWriteFrames(stream,
chunk,
count,
expectedDiscontinuity);
if (KFAILED(status) || status == NTLSTATUS_TIMEOUT) {
failurePhase = "stream-write";
failureStatus = status;
failureValue = submitted;
goto cleanup;
}
submitted += count;
}
status = KeAudioDrainStream(stream);
if (KFAILED(status)) {
failurePhase = "stream-drain";
failureStatus = status;
goto cleanup;
}
KE_AUDIO_STREAM_WAIT_CONDITION drainCondition = {
.Mask = KE_AUDIO_WAIT_DRAINED | KE_AUDIO_WAIT_FAILED | KE_AUDIO_WAIT_DISCONTINUITY,
.DrainedGeneration = startInfo.DrainedGeneration,
.DiscontinuityGeneration = expectedDiscontinuity,
};
status = KeAudioArmStreamWait(stream, &drainCondition);
if (KFAILED(status)) {
failurePhase = "drain-arm";
failureStatus = status;
goto cleanup;
}
status = KiAudioSelfTestWait(stream);
if (KFAILED(status) || status == NTLSTATUS_TIMEOUT) {
failurePhase = "drain-wait";
failureStatus = status;
goto cleanup;
}
status = KeAudioQueryStream(stream, &streamAfter);
if (KFAILED(status)) {
failurePhase = "final-stream-query";
failureStatus = status;
goto cleanup;
}
haveStreamAfter = 1;
if (streamAfter.State != KeAudioStreamStopped ||
streamAfter.DrainedGeneration != startInfo.DrainedGeneration + 1u ||
streamAfter.BufferedFrames != 0 || streamAfter.FramesSubmitted != totalFrames ||
streamAfter.FramesConsumed != totalFrames || streamAfter.FramesPresented != totalFrames ||
streamAfter.FramesDiscarded != 0 || streamAfter.Underruns != 0 ||
streamAfter.DiscontinuityGeneration != expectedDiscontinuity) {
failurePhase = "final-stream-counters";
failureStatus = NTLSTATUS_DEVICE_ERROR;
failureValue = streamAfter.FramesPresented;
goto cleanup;
}
status = KiAudioSelfTestQueryEndpoint(endpointId, &endpointAfter);
if (KFAILED(status)) {
failurePhase = "final-endpoint-query";
failureStatus = status;
goto cleanup;
}
haveEndpointAfter = 1;
uint64_t mixedPeriods = endpointAfter.PeriodsMixed - endpointBefore.PeriodsMixed;
uint64_t completedPeriods = endpointAfter.PeriodsCompleted - endpointBefore.PeriodsCompleted;
uint64_t interruptCount = endpointAfter.InterruptCount - endpointBefore.InterruptCount;
uint64_t endpointUnderruns = endpointAfter.Underruns - endpointBefore.Underruns;
uint64_t endpointDiscontinuities = endpointAfter.DiscontinuityGeneration -
endpointBefore.DiscontinuityGeneration;
uint64_t positionFrames = endpointAfter.HardwarePositionFrames -
endpointBefore.HardwarePositionFrames;
if (!mixedPeriods || !completedPeriods || !interruptCount ||
endpointUnderruns || endpointDiscontinuities ||
positionFrames + endpointAfter.FramesPerPeriod < totalFrames) {
failurePhase = "final-endpoint-counters";
failureStatus = NTLSTATUS_DEVICE_ERROR;
failureValue = positionFrames;
goto cleanup;
}
cleanup:
if (stream && !haveStreamAfter && KSUCCESS(KeAudioQueryStream(stream, &streamAfter)))
haveStreamAfter = 1;
if (haveEndpointBefore && !haveEndpointAfter &&
KSUCCESS(KiAudioSelfTestQueryEndpoint(endpointId, &endpointAfter)))
haveEndpointAfter = 1;
if (haveEndpointBefore && haveEndpointAfter && haveStreamAfter)
KiAudioSelfTestPrintCounters(endpointId,
&endpointBefore,
&endpointAfter,
&streamAfter,
expectedDiscontinuity);
if (stream) {
KE_AUDIO_STREAM_INFO cleanupInfo;
if (KSUCCESS(KeAudioQueryStream(stream, &cleanupInfo)) &&
cleanupInfo.State != KeAudioStreamStopped &&
cleanupInfo.State != KeAudioStreamFailed &&
cleanupInfo.State != KeAudioStreamClosed)
(void)KeAudioStopStream(stream);
}
if (chunk)
MmFreePool(chunk);
if (stream)
ObDereferenceObject(&stream->Header);
if (failurePhase) {
DbgPrint("AUDIO final selftest: FAIL phase=%s status=0x%x value=%llu\n",
failurePhase,
failureStatus,
(unsigned long long)failureValue);
return;
}
DbgPrint("AUDIO final selftest: PASS\n");
}