Adds an option to start VMM immediately (#1019)
Some checks are pending
Development Build / Build (push) Waiting to run
Development Build / Update PRs (push) Waiting to run

This commit is contained in:
Putta Khunchalee 2024-10-06 20:24:38 +07:00 committed by GitHub
parent ff0163e303
commit 802de64433
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 177 additions and 102 deletions

1
.vscode/launch.json vendored
View File

@ -23,6 +23,7 @@
"name": "Kernel",
"type": "lldb",
"request": "custom",
"preLaunchTask": "Launch VMM (Debug)",
"initCommands": [
"platform select remote-gdb-server",
"platform connect connect://localhost:1234"

32
.vscode/tasks.json vendored Normal file
View File

@ -0,0 +1,32 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "Launch VMM (Debug)",
"detail": "Launch the GUI then start the VMM in debug mode",
"type": "process",
"isBackground": true,
"runOptions": {
"instanceLimit": 1
},
"linux": {
"command": "${workspaceFolder}/build/gui/obliteration"
},
"osx": {
"command": "${workspaceFolder}/build/gui/obliteration.app/Contents/MacOS/obliteration"
},
"windows": {
"command": "${workspaceFolder}/build/gui/Obliteration.exe",
"options": {
"env": {
"Path": "${env:Path};${env:CMAKE_PREFIX_PATH}\\bin"
}
}
},
"args": [
"--debug",
"127.0.0.1:1234"
]
}
]
}

View File

@ -7,6 +7,7 @@
#endif
#include <QApplication>
#include <QCommandLineParser>
#include <QList>
#include <QMessageBox>
#include <QMetaObject>
@ -57,6 +58,14 @@ int main(int argc, char *argv[])
QGuiApplication::setWindowIcon(QIcon(":/resources/obliteration-icon.png"));
// Parse arguments.
QCommandLineParser args;
args.setApplicationDescription("Virtualization stack for Obliteration");
args.addHelpOption();
args.addOption(Args::debug);
args.process(app);
// Hook Rust panic.
QObject panic;
@ -199,11 +208,11 @@ int main(int argc, char *argv[])
}
}
// Run main window.
// Setup main window.
#ifdef __APPLE__
MainWindow win;
MainWindow win(args);
#else
MainWindow win(&vulkan, std::move(vkDevices));
MainWindow win(args, &vulkan, std::move(vkDevices));
#endif
if (!win.loadProfiles() || !win.loadGames()) {
@ -212,5 +221,12 @@ int main(int argc, char *argv[])
win.restoreGeometry();
// Run main window.
auto debug = args.value(Args::debug);
if (!debug.isEmpty()) {
win.startVmm(debug);
}
return QApplication::exec();
}

View File

@ -14,6 +14,8 @@
#include <QAction>
#include <QApplication>
#include <QCloseEvent>
#include <QCommandLineOption>
#include <QCommandLineParser>
#include <QDesktopServices>
#include <QDir>
#include <QFile>
@ -35,11 +37,19 @@
#include <string.h>
namespace Args {
const QCommandLineOption debug("debug", "Immediate launch the VMM in debug mode.", "addr", "127.0.0.1:1234");
}
#ifdef __APPLE__
MainWindow::MainWindow() :
MainWindow::MainWindow(const QCommandLineParser &args) :
#else
MainWindow::MainWindow(QVulkanInstance *vulkan, QList<VkPhysicalDevice> &&vkDevices) :
MainWindow::MainWindow(
const QCommandLineParser &args,
QVulkanInstance *vulkan,
QList<VkPhysicalDevice> &&vkDevices) :
#endif
m_args(args),
m_main(nullptr),
m_profiles(nullptr),
m_games(nullptr),
@ -341,95 +351,6 @@ void MainWindow::saveProfile(Profile *p)
}
}
void MainWindow::startVmm(const QString &debugAddr)
{
// Get full path to kernel binary.
std::string kernel;
if (QFile::exists(".obliteration-development")) {
auto b = std::filesystem::current_path();
#ifdef _WIN32
auto target = L"x86_64-unknown-none";
#elif defined(__aarch64__)
auto target = "aarch64-unknown-none-softfloat";
#else
auto target = "x86_64-unknown-none";
#endif
#if defined(_WIN32) && defined(NDEBUG)
kernel = (b / L"target" / target / L"release" / L"obkrnl").u8string();
#elif defined(_WIN32) && !defined(NDEBUG)
kernel = (b / L"target" / target / L"debug" / L"obkrnl").u8string();
#elif defined(NDEBUG)
kernel = (b / "target" / target / "release" / "obkrnl").u8string();
#else
kernel = (b / "target" / target / "debug" / "obkrnl").u8string();
#endif
} else {
#ifdef _WIN32
std::filesystem::path b(QCoreApplication::applicationDirPath().toStdString(), std::filesystem::path::native_format);
b /= L"share";
b /= L"obkrnl";
kernel = b.u8string();
#else
auto b = std::filesystem::path(QCoreApplication::applicationDirPath().toStdString(), std::filesystem::path::native_format).parent_path();
#ifdef __APPLE__
b /= "Resources";
#else
b /= "share";
#endif
b /= "obkrnl";
kernel = b.u8string();
#endif
}
// Swap launch settings with the screen before getting a Vulkan surface otherwise it will fail.
m_main->setCurrentIndex(1);
// Run.
auto debug = debugAddr.toStdString();
VmmScreen screen;
Rust<RustError> error;
Rust<Vmm> vmm;
memset(&screen, 0, sizeof(screen));
#ifdef __APPLE__
screen.view = m_screen->winId();
#else
screen.vk_instance = reinterpret_cast<size_t>(m_screen->vulkanInstance()->vkInstance());
screen.vk_device = reinterpret_cast<size_t>(m_launch->currentDisplayDevice()->handle());
screen.vk_surface = reinterpret_cast<size_t>(QVulkanInstance::surfaceForWindow(m_screen));
if (!screen.vk_surface) {
m_main->setCurrentIndex(0);
QMessageBox::critical(this, "Error", "Couldn't create VkSurfaceKHR.");
return;
}
#endif
vmm = vmm_run(
kernel.c_str(),
&screen,
m_launch->currentProfile(),
debug.empty() ? nullptr : debug.c_str(),
MainWindow::vmmHandler,
this,
&error);
if (!vmm) {
m_main->setCurrentIndex(0);
QMessageBox::critical(
this,
"Error",
QString("Couldn't run %1: %2").arg(kernel.c_str()).arg(error_message(error)));
return;
}
m_vmm = std::move(vmm);
m_screen->requestUpdate();
}
void MainWindow::updateScreen()
{
// Do nothing if the VMM is not running.
@ -462,15 +383,21 @@ void MainWindow::vmmError(const QString &msg)
QMessageBox::critical(this, "Error", msg);
m_main->setCurrentIndex(0);
if (m_args.isSet(Args::debug)) {
close();
} else {
m_main->setCurrentIndex(0);
}
}
void MainWindow::waitingDebugger(const QString &addr)
{
QMessageBox::information(
this,
"Debug",
QString("The VMM are waiting for a debugger at %1.").arg(addr));
if (!m_args.isSet(Args::debug)) {
QMessageBox::information(
this,
"Debug",
QString("The VMM are waiting for a debugger at %1.").arg(addr));
}
}
void MainWindow::waitKernelExit(bool success)
@ -564,6 +491,95 @@ void MainWindow::restoreGeometry()
}
}
void MainWindow::startVmm(const QString &debugAddr)
{
// Get full path to kernel binary.
std::string kernel;
if (QFile::exists(".obliteration-development")) {
auto b = std::filesystem::current_path();
#ifdef _WIN32
auto target = L"x86_64-unknown-none";
#elif defined(__aarch64__)
auto target = "aarch64-unknown-none-softfloat";
#else
auto target = "x86_64-unknown-none";
#endif
#if defined(_WIN32) && defined(NDEBUG)
kernel = (b / L"target" / target / L"release" / L"obkrnl").u8string();
#elif defined(_WIN32) && !defined(NDEBUG)
kernel = (b / L"target" / target / L"debug" / L"obkrnl").u8string();
#elif defined(NDEBUG)
kernel = (b / "target" / target / "release" / "obkrnl").u8string();
#else
kernel = (b / "target" / target / "debug" / "obkrnl").u8string();
#endif
} else {
#ifdef _WIN32
std::filesystem::path b(QCoreApplication::applicationDirPath().toStdString(), std::filesystem::path::native_format);
b /= L"share";
b /= L"obkrnl";
kernel = b.u8string();
#else
auto b = std::filesystem::path(QCoreApplication::applicationDirPath().toStdString(), std::filesystem::path::native_format).parent_path();
#ifdef __APPLE__
b /= "Resources";
#else
b /= "share";
#endif
b /= "obkrnl";
kernel = b.u8string();
#endif
}
// Swap launch settings with the screen before getting a Vulkan surface otherwise it will fail.
m_main->setCurrentIndex(1);
// Run.
auto debug = debugAddr.toStdString();
VmmScreen screen;
Rust<RustError> error;
Rust<Vmm> vmm;
memset(&screen, 0, sizeof(screen));
#ifdef __APPLE__
screen.view = m_screen->winId();
#else
screen.vk_instance = reinterpret_cast<size_t>(m_screen->vulkanInstance()->vkInstance());
screen.vk_device = reinterpret_cast<size_t>(m_launch->currentDisplayDevice()->handle());
screen.vk_surface = reinterpret_cast<size_t>(QVulkanInstance::surfaceForWindow(m_screen));
if (!screen.vk_surface) {
m_main->setCurrentIndex(0);
QMessageBox::critical(this, "Error", "Couldn't create VkSurfaceKHR.");
return;
}
#endif
vmm = vmm_run(
kernel.c_str(),
&screen,
m_launch->currentProfile(),
debug.empty() ? nullptr : debug.c_str(),
MainWindow::vmmHandler,
this,
&error);
if (!vmm) {
m_main->setCurrentIndex(0);
QMessageBox::critical(
this,
"Error",
QString("Couldn't run %1: %2").arg(kernel.c_str()).arg(error_message(error)));
return;
}
m_vmm = std::move(vmm);
m_screen->requestUpdate();
}
bool MainWindow::requireVmmStopped()
{
if (m_vmm) {

View File

@ -13,21 +13,27 @@ class GameListModel;
class LaunchSettings;
class LogsViewer;
class ProfileList;
class QCommandLineOption;
class QCommandLineParser;
class QStackedWidget;
class Screen;
class MainWindow final : public QMainWindow {
public:
#ifdef __APPLE__
MainWindow();
MainWindow(const QCommandLineParser &args);
#else
MainWindow(QVulkanInstance *vulkan, QList<VkPhysicalDevice> &&vkDevices);
MainWindow(
const QCommandLineParser &args,
QVulkanInstance *vulkan,
QList<VkPhysicalDevice> &&vkDevices);
#endif
~MainWindow() override;
bool loadProfiles();
bool loadGames();
void restoreGeometry();
void startVmm(const QString &debugAddr);
protected:
void closeEvent(QCloseEvent *event) override;
@ -38,7 +44,6 @@ private slots:
void reportIssue();
void aboutObliteration();
void saveProfile(Profile *p);
void startVmm(const QString &debugAddr);
void updateScreen();
private:
void vmmError(const QString &msg);
@ -50,6 +55,7 @@ private:
static void vmmHandler(const VmmEvent *ev, void *cx);
const QCommandLineParser &m_args;
QStackedWidget *m_main;
ProfileList *m_profiles;
GameListModel *m_games;
@ -58,3 +64,7 @@ private:
QPointer<LogsViewer> m_logs;
Rust<Vmm> m_vmm; // Destroy first.
};
namespace Args {
extern const QCommandLineOption debug;
}