From 2e92b7ae324dc3459ef81815edf0fe86d682d35b Mon Sep 17 00:00:00 2001 From: Alexander Boettcher Date: Mon, 22 Jul 2024 10:20:44 +0200 Subject: [PATCH] nova: enable FPU AVX support Add extended FPU state detection and handling (via xsave and friends) to the kernel, which has to store/load more FPU state (~512 -> 2k++) during context switching of threads. Additional the referenced nova branch contains various optimization during VM destruction and cross core IPC resource caching. This FPU work is based upon upstream NOVA kernel and Hedron commits. Issue #5314 Fixes #3914 --- repos/base-nova/include/nova/syscall-generic.h | 3 ++- repos/base-nova/ports/nova.hash | 2 +- repos/base-nova/ports/nova.port | 2 +- repos/base-nova/src/core/platform.cc | 2 +- repos/base-nova/src/lib/base/vm.cc | 13 +++++++++++++ repos/base/include/spec/x86/cpu/vcpu_state.h | 3 +++ 6 files changed, 21 insertions(+), 4 deletions(-) diff --git a/repos/base-nova/include/nova/syscall-generic.h b/repos/base-nova/include/nova/syscall-generic.h index 69502fb9d5..8210e31b7b 100644 --- a/repos/base-nova/include/nova/syscall-generic.h +++ b/repos/base-nova/include/nova/syscall-generic.h @@ -417,6 +417,7 @@ namespace Nova { SYSCALL_SWAPGS = 1U << 23, /* SYSCALL and SWAPGS MSRs */ TPR = 1U << 24, /* TPR and TPR threshold */ TSC_AUX = 1U << 25, /* IA32_TSC_AUX used by rdtscp */ + XSAVE = 1U << 26, /* XCR and XSS used with XSAVE */ FPU = 1U << 31, /* FPU state */ IRQ = EFL | STA | INJ | TSC, @@ -660,8 +661,8 @@ namespace Nova { #endif unsigned long long qual[2]; /* exit qualification */ unsigned ctrl[2]; - unsigned long long reserved; mword_t cr0, cr2, cr3, cr4; + unsigned long long xcr0, xss; mword_t pdpte[4]; #ifdef __x86_64__ mword_t cr8, efer; diff --git a/repos/base-nova/ports/nova.hash b/repos/base-nova/ports/nova.hash index 3e6b2740d5..321dbd6073 100644 --- a/repos/base-nova/ports/nova.hash +++ b/repos/base-nova/ports/nova.hash @@ -1 +1 @@ -ff82f8cb5bb9b87bd8c05048863c564d05897b2c +e8997fb0870b6f8bdcb6da34a9b333ed4a304305 diff --git a/repos/base-nova/ports/nova.port b/repos/base-nova/ports/nova.port index b289528b60..736a144c68 100644 --- a/repos/base-nova/ports/nova.port +++ b/repos/base-nova/ports/nova.port @@ -4,7 +4,7 @@ DOWNLOADS := nova.git # r10 branch URL(nova) := https://github.com/alex-ab/NOVA.git -REV(nova) := a19cd2a58d37f6f517e9928fe89a413a1eaa05d2 +REV(nova) := bca1aa3553d8c5df4f4b6ed5a2ee72f69bdf7a7f DIR(nova) := src/kernel/nova PATCHES := $(sort $(wildcard $(REP_DIR)/patches/*.patch)) diff --git a/repos/base-nova/src/core/platform.cc b/repos/base-nova/src/core/platform.cc index 421c67fb1f..10f0a4c781 100644 --- a/repos/base-nova/src/core/platform.cc +++ b/repos/base-nova/src/core/platform.cc @@ -725,7 +725,7 @@ Core::Platform::Platform() /* show all warnings/errors after init_core_log setup core_log */ if (warn_reorder) warning("re-ordering of CPU ids for SMT and P/E cores failed"); - if (hip.api_version != 9) + if (hip.api_version != 10) error("running on a unsupported kernel API version ", hip.api_version); if (binaries_end != core_virt_end) error("mismatch in address layout of binaries with core"); diff --git a/repos/base-nova/src/lib/base/vm.cc b/repos/base-nova/src/lib/base/vm.cc index 3d0639ef7e..bd2c407ded 100644 --- a/repos/base-nova/src/lib/base/vm.cc +++ b/repos/base-nova/src/lib/base/vm.cc @@ -134,6 +134,7 @@ struct Nova_vcpu : Rpc_client, Noncopyable mtd |= Nova::Mtd::SYSCALL_SWAPGS; mtd |= Nova::Mtd::TPR; mtd |= Nova::Mtd::QUAL; + mtd |= Nova::Mtd::XSAVE; mtd |= Nova::Mtd::FPU; return Nova::Mtd(mtd); @@ -334,6 +335,11 @@ void Nova_vcpu::_read_nova_state(Nova::Utcb &utcb) _vcpu_state.tpr.charge(utcb.read_tpr()); _vcpu_state.tpr_threshold.charge(utcb.read_tpr_threshold()); } + + if (utcb.mtd & Nova::Mtd::XSAVE) { + _vcpu_state.xcr0.charge(utcb.xcr0); + _vcpu_state.xss.charge(utcb.xss); + } } @@ -541,6 +547,13 @@ void Nova_vcpu::_write_nova_state(Nova::Utcb &utcb) utcb.write_tpr_threshold(_vcpu_state.tpr_threshold.value()); } + if (_vcpu_state.xcr0.charged() || _vcpu_state.xss.charged()) { + utcb.xcr0 = _vcpu_state.xcr0.value(); + utcb.xss = _vcpu_state.xss.value(); + + utcb.mtd |= Nova::Mtd::XSAVE; + } + if (_vcpu_state.fpu.charged()) { utcb.mtd |= Nova::Mtd::FPU; _vcpu_state.fpu.with_state([&] (Vcpu_state::Fpu::State const &fpu) { diff --git a/repos/base/include/spec/x86/cpu/vcpu_state.h b/repos/base/include/spec/x86/cpu/vcpu_state.h index 9d2058e17c..6141e566b1 100644 --- a/repos/base/include/spec/x86/cpu/vcpu_state.h +++ b/repos/base/include/spec/x86/cpu/vcpu_state.h @@ -195,6 +195,9 @@ class Genode::Vcpu_state Register tpr { }; Register tpr_threshold { }; + Register xcr0 { }; + Register xss { }; + unsigned exit_reason { }; class Fpu : Noncopyable