ohhhhhhhhhhh (exclude linux-extra-rootfs.img build artifact)

This commit is contained in:
Linehu
2026-10-01 23:13:42 +08:00
parent 737a2cb0db
commit 1074962546
533 changed files with 133239 additions and 5460 deletions
+205
View File
@@ -0,0 +1,205 @@
/* linux_xsave.c — L2 guest XSAVE save/restore.
*
* Host UTSM is compiled -mno-sse. A naive XRSTOR of guest AVX/SSE
* state #GPs. Advertise XSAVE to the Linux guest only after we can
* XSAVE the guest area before returning to DSK, and XRSTOR it again
* on the next vmresume.
*
* RFBM/XCR0 = 7 (x87+SSE+AVX/YMM). persist glibc is x86-64-v3. */
#include <utsm/linux_xsave.h>
#include <utsm/vmx.h>
#include <utsm/log.h>
#include <utsm/types.h>
#define LINUX_XSAVE_XCR0 0x7ULL
#define LINUX_XSAVE_BYTES 832u
#define LINUX_XSAVE_YMM_SIZE 256u
#define LINUX_XSAVE_YMM_OFF 576u
static int g_xsave_ok;
static u64 g_guest_xcr0 = LINUX_XSAVE_XCR0;
static u64 g_host_xcr0 = LINUX_XSAVE_XCR0;
static u8 g_guest_xsave[4096] __attribute__((aligned(64)));
static u8 g_host_xsave[4096] __attribute__((aligned(64)));
static void xsave_zero(u8 *p, usize n) {
for (usize i = 0; i < n; i++)
p[i] = 0;
}
static void xsave_enable_osxsave(void) {
u64 cr4;
__asm__ volatile("mov %%cr4, %0" : "=r"(cr4));
if (!(cr4 & CR4_OSXSAVE)) {
cr4 |= CR4_OSXSAVE;
__asm__ volatile("mov %0, %%cr4" : : "r"(cr4) : "memory");
}
/* VM-exit reloads HOST_CR4. Keep OSXSAVE so later XSAVE is legal. */
vmx_vmcs_write(VMCS_HOST_CR4, cr4 | CR4_VMXE);
}
static void xsave_xsetbv(u64 xcr0) {
u32 lo = (u32)xcr0;
u32 hi = (u32)(xcr0 >> 32);
__asm__ volatile(".byte 0x0f, 0x01, 0xd1"
:
: "a"(lo), "c"(0), "d"(hi)
: "memory");
}
static void xsave_mem(void *ptr, u64 rfbm) {
u32 lo = (u32)rfbm;
u32 hi = (u32)(rfbm >> 32);
__asm__ volatile(".byte 0x0f, 0xae, 0x27" /* xsave (%rdi) */
:
: "D"(ptr), "a"(lo), "d"(hi)
: "memory");
}
static void xrstor_mem(void *ptr, u64 rfbm) {
u32 lo = (u32)rfbm;
u32 hi = (u32)(rfbm >> 32);
__asm__ volatile(".byte 0x0f, 0xae, 0x2f" /* xrstor (%rdi) */
:
: "D"(ptr), "a"(lo), "d"(hi)
: "memory");
}
int linux_xsave_available(void) {
return g_xsave_ok;
}
void linux_xsave_init(void) {
u32 a, b, c, d;
if (g_xsave_ok)
return;
__asm__ volatile("cpuid"
: "=a"(a), "=b"(b), "=c"(c), "=d"(d)
: "a"(1), "c"(0));
if (!(c & (1u << 26))) {
log_warn("[LINUX] XSAVE not in host CPUID; persist glibc stays hidden");
return;
}
xsave_zero(g_guest_xsave, sizeof(g_guest_xsave));
xsave_zero(g_host_xsave, sizeof(g_host_xsave));
g_guest_xcr0 = LINUX_XSAVE_XCR0;
g_host_xcr0 = LINUX_XSAVE_XCR0;
xsave_enable_osxsave();
xsave_xsetbv(LINUX_XSAVE_XCR0);
/* Init-state XRSTOR so the first vmlaunch does not inherit host junk. */
xrstor_mem(g_guest_xsave, LINUX_XSAVE_XCR0);
g_xsave_ok = 1;
log_info("[LINUX] XSAVE ready for L2 (x87+SSE+AVX, XCR0=7)");
log_hex64("[LINUX] XSAVE area bytes=", LINUX_XSAVE_BYTES);
}
void linux_xsave_save_guest(void) {
if (!g_xsave_ok)
return;
xsave_enable_osxsave();
xsave_xsetbv(g_guest_xcr0);
xsave_mem(g_guest_xsave, g_guest_xcr0);
}
void linux_xsave_load_guest(void) {
if (!g_xsave_ok)
return;
xsave_enable_osxsave();
xsave_xsetbv(g_guest_xcr0);
xrstor_mem(g_guest_xsave, g_guest_xcr0);
}
void linux_xsave_save_host(void) {
if (!g_xsave_ok)
return;
xsave_enable_osxsave();
xsave_xsetbv(g_host_xcr0);
xsave_mem(g_host_xsave, g_host_xcr0);
}
void linux_xsave_load_host(void) {
if (!g_xsave_ok)
return;
xsave_enable_osxsave();
xsave_xsetbv(g_host_xcr0);
xrstor_mem(g_host_xsave, g_host_xcr0);
}
void linux_xsave_set_guest_xcr0(u64 xcr0) {
u64 allowed = LINUX_XSAVE_XCR0;
u64 v = xcr0 & allowed;
static int logged;
if (!g_xsave_ok)
return;
/* Intel requires x87. Keep SSE if this build advertises it. */
if (!(v & 1ULL))
v |= 1ULL;
if ((allowed & 2ULL) && !(v & 2ULL))
v |= 2ULL;
if (!logged && v != xcr0) {
logged = 1;
log_hex64("[LINUX] XSETBV clamped from=", xcr0);
log_hex64("[LINUX] XSETBV clamped to=", v);
}
g_guest_xcr0 = v;
xsave_enable_osxsave();
xsave_xsetbv(v);
}
void linux_xsave_adjust_cpuid(u32 leaf, u32 subleaf,
u32 *eax, u32 *ebx, u32 *ecx, u32 *edx,
u64 guest_cr4) {
if (!eax || !ebx || !ecx || !edx)
return;
if (!g_xsave_ok) {
if (leaf == 1) {
*ecx &= ~((1u << 26) | (1u << 27) | (1u << 28));
}
if (leaf == 0xD) {
*eax = 0;
*ebx = 0;
*ecx = 0;
*edx = 0;
}
return;
}
if (leaf == 1) {
*ecx |= (1u << 26); /* XSAVE */
if (guest_cr4 & CR4_OSXSAVE)
*ecx |= (1u << 27);
else
*ecx &= ~(1u << 27);
*ecx |= (1u << 28); /* AVX / XCR0 bit 2 */
return;
}
if (leaf != 0xD)
return;
/* Hide XSAVEOPT/XSAVEC/XSAVES. Standard XSAVE only. */
if (subleaf == 0) {
*eax = (u32)LINUX_XSAVE_XCR0;
*ebx = LINUX_XSAVE_BYTES;
*ecx = LINUX_XSAVE_BYTES;
*edx = 0;
} else if (subleaf == 2) {
*eax = LINUX_XSAVE_YMM_SIZE;
*ebx = LINUX_XSAVE_YMM_OFF;
*ecx = 0;
*edx = 0;
} else {
*eax = 0;
*ebx = 0;
*ecx = 0;
*edx = 0;
}
}