Index: machineprocess.cpp =================================================================== --- machineprocess.cpp +++ machineprocess.cpp 2007-07-18 00:20:00.000000000 +0200 @@ -37,6 +37,10 @@ cdRomPathString = QString(); snapshotEnabled = false; networkEnabled = false; + kqemuEnabled = false; + kqemuKernelEnabled = false; + kvmEnabled = false; + } void MachineProcess::start() @@ -70,6 +74,16 @@ arguments << "-smp" << QString::number(cpuInt); + if (kqemuEnabled) { + if (kqemuKernelEnabled) + arguments << "-kernel-kqemu"; + } + else + arguments << "-no-kqemu"; + + if (!kvmEnabled) + arguments << "-no-kvm"; + if (mouseEnabled) arguments << "-usb" << "-usbdevice" << "tablet"; @@ -213,3 +227,27 @@ { cpuInt = value; } + +void MachineProcess::kqemu(int value) +{ + if (value == Qt::Checked) + kqemuEnabled = true; + else + kqemuEnabled = false; +} + +void MachineProcess::kqemuKernel(int value) +{ + if (value == Qt::Checked) + kqemuKernelEnabled = true; + else + kqemuKernelEnabled = false; +} + +void MachineProcess::kvm(int value) +{ + if (value == Qt::Checked) + kvmEnabled = true; + else + kvmEnabled = false; +} Index: machineprocess.h =================================================================== --- machineprocess.h +++ machineprocess.h 2007-07-18 09:24:51.000000000 +0200 @@ -46,6 +46,9 @@ void mouse(int value); void time(int value); void cpu(int value); + void kqemu(int value); + void kqemuKernel(int value); + void kvm(int value); private: QString pathString; @@ -57,6 +60,9 @@ bool networkEnabled; bool mouseEnabled; bool timeEnabled; + bool kqemuEnabled; + bool kqemuKernelEnabled; + bool kvmEnabled; int memoryInt; int cpuInt; Index: machinetab.cpp =================================================================== --- machinetab.cpp +++ machinetab.cpp 2007-07-18 09:41:03.000000000 +0200 @@ -22,12 +22,16 @@ ****************************************************************************/ #include <QtGui> +#include <stdint.h> #include "machineprocess.h" #include "config.h" #include "machinetab.h" +static bool kqemu_possible(void); +static bool kvm_possible(void); + MachineTab::MachineTab(QTabWidget *parent, const QString &fileName, const QString &myMachinesPathParent) : QWidget(parent) { @@ -292,6 +296,64 @@ networkFrameLayout->addWidget(networkCheckBox); //network section end + //cpu section start + cpuButton = new QPushButton(QIcon(":/images/processor.png"), tr("&Virtualizer / Processors"), this); + cpuButton->setCheckable(true); + devicesLayout->addWidget(cpuButton); + + cpuFrame = new QFrame(this); + cpuFrame->setVisible(false); + devicesLayout->addWidget(cpuFrame); + connect(cpuButton, SIGNAL(clicked(bool)), this, SLOT(closeAllSections())); + connect(cpuButton, SIGNAL(clicked(bool)), cpuFrame, SLOT(setVisible(bool))); + connect(cpuButton, SIGNAL(clicked(bool)), cpuButton, SLOT(setChecked(bool))); + + QVBoxLayout *cpuFrameLayout = new QVBoxLayout; + cpuFrame->setLayout(cpuFrameLayout); + + QLabel *qemuAcceleratorDescriptionLabel = new QLabel(tr("Choose what QEMU accelerator should be enabled for this " + "virtual machine. Hardware-assisted virtualization has " + "priority if it is available and is selected."), this); + qemuAcceleratorDescriptionLabel->setWordWrap(true); + cpuFrameLayout->addWidget(qemuAcceleratorDescriptionLabel); + + kqemuCheckBox = new QCheckBox(tr("Enable QEMU &Accelerator (KQEMU)"), this); + connect(kqemuCheckBox, SIGNAL(stateChanged(int)), machineProcess, SLOT(kqemu(int))); + cpuFrameLayout->addWidget(kqemuCheckBox); + if (!kqemu_possible()) + + kqemuCheckBox->setDisabled(true); + + kqemuKernelCheckBox = new QCheckBox(tr("Enable KQEMU &full virtualization"), this); + connect(kqemuKernelCheckBox, SIGNAL(stateChanged(int)), machineProcess, SLOT(kqemuKernel(int))); + cpuFrameLayout->addWidget(kqemuKernelCheckBox); + kqemuKernelCheckBox->setDisabled(true); + + kvmCheckBox = new QCheckBox(tr("Enable &KVM (Kernel-based Virtual Machine)"), this); + connect(kvmCheckBox, SIGNAL(stateChanged(int)), machineProcess, SLOT(kvm(int))); + cpuFrameLayout->addWidget(kvmCheckBox); + if (!kvm_possible()) + kvmCheckBox->setDisabled(true); + + QLabel *cpuDescriptionLabel = new QLabel(tr("<hr>Choose the number of virtual CPUs."), this); + cpuDescriptionLabel->setWordWrap(true); + cpuFrameLayout->addWidget(cpuDescriptionLabel); + + cpuSpinBox = new QSpinBox(this); + cpuSpinBox->setRange(1, 4); + cpuSpinBox->setValue(2); + connect(cpuSpinBox, SIGNAL(valueChanged(int)), machineProcess, SLOT(cpu(int))); + + QLabel *cpuLabel = new QLabel(tr("Virtual CPU(s)"), this); + + QHBoxLayout *cpuLayout = new QHBoxLayout; + cpuLayout->addWidget(cpuSpinBox); + cpuLayout->addWidget(cpuLabel); + cpuLayout->addStretch(); + cpuFrameLayout->addLayout(cpuLayout); + //cpu section end + + //other section start otherButton = new QPushButton(QIcon(":/images/" + iconTheme + "/other.png"), tr("&Other"), this); otherButton->setCheckable(true); @@ -319,23 +381,6 @@ connect(mouseCheckBox, SIGNAL(stateChanged(int)), machineProcess, SLOT(mouse(int))); otherFrameLayout->addWidget(mouseCheckBox); - QLabel *cpuDescriptionLabel = new QLabel(tr("<hr>Choose the number of virtual CPUs."), this); - cpuDescriptionLabel->setWordWrap(true); - otherFrameLayout->addWidget(cpuDescriptionLabel); - - cpuSpinBox = new QSpinBox(this); - cpuSpinBox->setRange(1, 4); - cpuSpinBox->setValue(2); - connect(cpuSpinBox, SIGNAL(valueChanged(int)), machineProcess, SLOT(cpu(int))); - - QLabel *cpuLabel = new QLabel(tr("Virtual CPU(s)"), this); - - QHBoxLayout *cpuLayout = new QHBoxLayout; - cpuLayout->addWidget(cpuSpinBox); - cpuLayout->addWidget(cpuLabel); - cpuLayout->addStretch(); - otherFrameLayout->addLayout(cpuLayout); - QLabel *timeDescriptionLabel = new QLabel(tr("<hr>Choose if the virtual machine should use " "the host machine clock."), this); timeDescriptionLabel->setWordWrap(true); @@ -373,6 +418,9 @@ connect(floppyLineEdit, SIGNAL(textChanged(QString)), this, SLOT(write())); connect(floppyBootCheckBox, SIGNAL(stateChanged(int)), this, SLOT(write())); connect(networkCheckBox, SIGNAL(stateChanged(int)), this, SLOT(write())); + connect(kqemuCheckBox, SIGNAL(stateChanged(int)), this, SLOT(write())); + connect(kqemuKernelCheckBox, SIGNAL(stateChanged(int)), this, SLOT(write())); + connect(kvmCheckBox, SIGNAL(stateChanged(int)), this, SLOT(write())); connect(mouseCheckBox, SIGNAL(stateChanged(int)), this, SLOT(write())); connect(timeCheckBox, SIGNAL(stateChanged(int)), this, SLOT(write())); connect(cpuSpinBox, SIGNAL(valueChanged(int)), this, SLOT(write())); @@ -445,6 +493,8 @@ floppyFrame->setVisible(false); networkButton->setChecked(false); networkFrame->setVisible(false); + cpuButton->setChecked(false); + cpuFrame->setVisible(false); otherButton->setChecked(false); otherFrame->setVisible(false); } @@ -501,6 +551,9 @@ floppyLineEdit->setText(QString()); floppyBootCheckBox->setChecked(false); networkCheckBox->setChecked(true); + kqemuCheckBox->setChecked(kqemu_possible()); + kqemuKernelCheckBox->setChecked(false); + kvmCheckBox->setChecked(false); mouseCheckBox->setChecked(true); timeCheckBox->setChecked(true); cpuSpinBox->setValue(1); @@ -515,6 +568,14 @@ floppyLineEdit->setText(child.firstChildElement("floppy").text()); floppyBootCheckBox->setChecked(child.firstChildElement("bootFromFloppy").text() == "true"); networkCheckBox->setChecked(child.firstChildElement("network").text() != "false"); + kqemuCheckBox->setChecked(kqemu_possible() && child.firstChildElement("kqemu").text() != "false"); + if (kqemuCheckBox->isChecked()) { + kqemuKernelCheckBox->setEnabled(true); + kqemuKernelCheckBox->setChecked(child.firstChildElement("kqemuKernel").text() == "true"); + } + else + kqemuKernelCheckBox->setDisabled(true); + kvmCheckBox->setChecked(kvm_possible() && child.firstChildElement("kvm").text() == "true"); mouseCheckBox->setChecked(child.firstChildElement("mouse").text() != "false"); timeCheckBox->setChecked(child.firstChildElement("time").text() != "false"); cpuSpinBox->setValue(child.firstChildElement("cpu").text().toInt()); @@ -555,6 +616,15 @@ changeValue("floppy", floppyLineEdit->text()); changeValue("bootFromFloppy", floppyBootCheckBox->isChecked() ? "true" : "false"); changeValue("network", networkCheckBox->isChecked() ? "true" : "false"); + changeValue("kqemu", kqemuCheckBox->isChecked() ? "true" : "false"); + if (kqemuCheckBox->isChecked()) + kqemuKernelCheckBox->setEnabled(true); + else { + kqemuKernelCheckBox->setDisabled(true); + kqemuKernelCheckBox->setChecked(false); + } + changeValue("kqemuKernel", kqemuKernelCheckBox->isChecked() ? "true" : "false"); + changeValue("kvm", kvmCheckBox->isChecked() ? "true" : "false"); changeValue("mouse", mouseCheckBox->isChecked() ? "true" : "false"); changeValue("time", timeCheckBox->isChecked() ? "true" : "false"); changeValue("cpu", QString::number(cpuSpinBox->value())); @@ -620,3 +690,67 @@ stopButton->setEnabled(false); startButton->setEnabled(true); } + +bool kqemu_possible(void) +{ +#if defined __i386__ || defined __x86_64__ + return true; +#endif + return false; +} + +#if defined __i386__ || defined __x86_64__ +static void cpuid(uint32_t op, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx) +{ + uint32_t a = eax ? *eax : 0; + uint32_t b = ebx ? *ebx : 0; + uint32_t c = ecx ? *ecx : 0; + uint32_t d = edx ? *edx : 0; + +#if defined __i386__ + __asm__ __volatile__ ("xchgl %%ebx,%0\n\t" + "cpuid \n\t" + "xchgl %%ebx,%0\n\t" + : "+r" (b), "=a" (a), "=c" (c), "=d" (d) + : "1" (op), "2" (c)); +#else + __asm__ __volatile__ ("cpuid" + : "=a" (a), "=b" (b), "=c" (c), "=d" (d) + : "0" (op), "2" (c)); +#endif + + if (eax) *eax = a; + if (ebx) *ebx = b; + if (ecx) *ecx = c; + if (edx) *edx = d; +} + +static bool kvm_detect(void) +{ + uint32_t eax, ecx; + cpuid(1, NULL, NULL, &ecx, NULL); + if (ecx & (1 << 5)) // VMX + return true; + + cpuid(0x80000000, &eax, NULL, NULL, NULL); + if ((eax & 0xffff0000) == 0x80000000 && eax >= 0x80000001) { + cpuid(0x80000001, NULL, NULL, &ecx, NULL); + if (ecx & (1 << 2)) // SVM + return true; + } + + return false; +} +#endif + +bool kvm_possible(void) +{ +#if defined __i386__ || defined __x86_64__ + static int is_kvm_possible = -1; + if (is_kvm_possible < 0) + is_kvm_possible = kvm_detect(); + return is_kvm_possible; +#endif + return false; +} + Index: machinetab.h =================================================================== --- machinetab.h +++ machinetab.h 2007-07-18 00:17:38.000000000 +0200 @@ -57,6 +57,9 @@ QCheckBox *floppyBootCheckBox; QCheckBox *mouseCheckBox; QCheckBox *timeCheckBox; + QCheckBox *kqemuCheckBox; + QCheckBox *kqemuKernelCheckBox; + QCheckBox *kvmCheckBox; QSpinBox *cpuSpinBox; QLineEdit *machineNameEdit; QLineEdit *hddPathLineEdit; @@ -76,6 +79,8 @@ QFrame *floppyFrame; QPushButton *networkButton; QFrame *networkFrame; + QPushButton *cpuButton; + QFrame *cpuFrame; QPushButton *otherButton; QFrame *otherFrame; Index: qtemu.qrc =================================================================== --- qtemu.qrc +++ qtemu.qrc 2007-07-18 00:16:40.000000000 +0200 @@ -14,6 +14,7 @@ <file>images/crystal/floppy.png</file> <file>images/crystal/cdimage.png</file> <file>images/crystal/network.png</file> + <file>images/processor.png</file> <file>images/crystal/other.png</file> <file>images/oxygen/qtemu.png</file>