[CPU] Host RBX is restored from the saved host frame below

This commit is contained in:
ParantezTech 2026-09-23 14:46:17 +03:00
parent 6d6a5a1a0d
commit a036bc1a48
2 changed files with 35 additions and 1 deletions

View File

@ -2610,6 +2610,7 @@ public sealed unsafe partial class DirectExecutionBackend : INativeCpuBackend, I
byte* code = (byte*)ptr;
int offset = 0;
EmitByte(code, ref offset, 0x48); EmitByte(code, ref offset, 0x89); EmitByte(code, ref offset, 0xC3); // mov rbx,rax
EmitByte(code, ref offset, 0x48); // sub rsp, 0x20
EmitByte(code, ref offset, 0x83);
EmitByte(code, ref offset, 0xEC);
@ -2639,6 +2640,7 @@ public sealed unsafe partial class DirectExecutionBackend : INativeCpuBackend, I
EmitByte(code, ref offset, 0x5E);
EmitByte(code, ref offset, 0x5F);
EmitByte(code, ref offset, 0x5D);
EmitByte(code, ref offset, 0x48); EmitByte(code, ref offset, 0x89); EmitByte(code, ref offset, 0xD8); // mov rax,rbx
EmitByte(code, ref offset, 0x5B);
EmitByte(code, ref offset, 0xC3);

View File

@ -82,7 +82,24 @@ public sealed class Gen5NativeReturnSmokeTests
]);
}
private static void ExecuteSyntheticGuest(byte[]? callbackInstructions = null)
[Fact]
public async Task SyntheticGen5Continuation_PreservesFullReturnValue()
{
if (!IsSupportedHost)
return;
if (Environment.GetEnvironmentVariable(WorkerEnvironmentVariable) != "1")
{
var result = await RunIsolatedWorker(nameof(SyntheticGen5Continuation_PreservesFullReturnValue));
Assert.True(result.Completed, result.Output);
Assert.True(result.ExitCode == 0, result.Output);
return;
}
ExecuteSyntheticGuest(continuation: true);
}
private static void ExecuteSyntheticGuest(byte[]? callbackInstructions = null, bool continuation = false)
{
using var memory = new PhysicalVirtualMemory();
var image = new SelfLoader().Load(BuildSyntheticElf(callbackInstructions), memory);
@ -119,6 +136,21 @@ public sealed class Gen5NativeReturnSmokeTests
Assert.Null(dispatcher.LastNotImplementedInfo);
var callerContext = new CpuContext(new TrackedCpuMemory(memory), Generation.Gen5);
if (continuation)
{
Assert.True(memory.TryAllocateAtOrAbove(0x1_0000_0000, 0x4000, false, 0x4000, out var stack));
callerContext[CpuRegister.Rsp] = stack + 0x4000 - sizeof(ulong);
// Resume directly into mov rax, imm64; ret through the shared guest return stub.
var execute = typeof(DirectExecutionBackend).GetMethod(
"ExecuteGuestContinuationEntry", BindingFlags.Instance | BindingFlags.NonPublic)!;
object?[] arguments = [callerContext, image.EntryPoint + 3, callerContext[CpuRegister.Rsp],
"synthetic-native-continuation-return", null];
var exitReason = execute.Invoke(backend, arguments);
Assert.True(exitReason?.ToString() == "Returned", arguments[4]?.ToString());
Assert.Equal(CallbackReturnValue, callerContext[CpuRegister.Rax]);
return;
}
ulong dataAddress = 0;
var recoveryCounter = typeof(DirectExecutionBackend).GetField(
"_sse4aInstructionsEmulated", BindingFlags.Static | BindingFlags.NonPublic)!;