# Node ID 46ad52c66c874586162b9952265dce28186b58c9 # Parent cd09bde69eefb21140e6edf81c77dbf96e3ec2ed diff --git a/src/arch/x86/system.hh b/src/arch/x86/system.hh --- a/src/arch/x86/system.hh +++ b/src/arch/x86/system.hh @@ -75,6 +75,11 @@ const uint64_t ISTPhysAddr = 0x64000; const uint64_t pageTablePhysAddr = 0x70000; + + /* pseudo I/O port used by syscall handler */ + const uint16_t syscallPort = 0x0248; + /* pseudo I/O port used by page fault handler */ + const uint16_t faultPort = 0x0244; } class X86System : public System diff --git a/src/cpu/kvm/base.hh b/src/cpu/kvm/base.hh --- a/src/cpu/kvm/base.hh +++ b/src/cpu/kvm/base.hh @@ -666,6 +666,7 @@ * contain other data such as the MMIO ring buffer. */ struct kvm_run *_kvmRun; + private: /** * Coalesced MMIO ring buffer. NULL if coalesced MMIO is not * supported. diff --git a/src/cpu/kvm/base.cc b/src/cpu/kvm/base.cc --- a/src/cpu/kvm/base.cc +++ b/src/cpu/kvm/base.cc @@ -85,8 +85,14 @@ panic("KVM: Failed to determine host page size (%i)\n", errno); - thread = new SimpleThread(this, 0, params->system, - params->itb, params->dtb, params->isa[0]); + if (FullSystem) + thread = new SimpleThread(this, 0, params->system, params->itb, params->dtb, + params->isa[0]); + else + thread = new SimpleThread(this, /* thread_num */ 0, params->system, + params->workload[0], params->itb, + params->dtb, params->isa[0]); + thread->setStatus(ThreadContext::Halted); tc = thread->getTC(); threadContexts.push_back(tc); diff --git a/src/cpu/kvm/x86_cpu.hh b/src/cpu/kvm/x86_cpu.hh --- a/src/cpu/kvm/x86_cpu.hh +++ b/src/cpu/kvm/x86_cpu.hh @@ -148,6 +148,17 @@ Tick handleKvmExitIRQWindowOpen(); /** + * Handle exit caused by executing a syscall in SE mode. + */ + Tick handleKvmExitSysCall(); + + /** + * Handle exit caused by a page fault, as a consequence + * of stack growth, in SE mode. + */ + Tick handleKvmExitPageFault(); + + /** * Check if there are pending events in the vCPU that prevents it * from being drained. * diff --git a/src/cpu/kvm/x86_cpu.cc b/src/cpu/kvm/x86_cpu.cc --- a/src/cpu/kvm/x86_cpu.cc +++ b/src/cpu/kvm/x86_cpu.cc @@ -38,8 +38,10 @@ #include "arch/x86/cpuid.hh" #include "arch/x86/utility.hh" #include "arch/registers.hh" +#include "arch/x86/system.hh" #include "cpu/kvm/base.hh" #include "cpu/kvm/x86_cpu.hh" +#include "sim/sim_exit.hh" #include "debug/Drain.hh" #include "debug/Kvm.hh" #include "debug/KvmContext.hh" @@ -1309,10 +1311,17 @@ X86KvmCPU::handleKvmExitIO() { struct kvm_run &kvm_run(*getKvmRunState()); + uint16_t port(kvm_run.io.port); + + if (port == syscallPort) + return handleKvmExitSysCall(); + else if (port == faultPort) + return handleKvmExitPageFault(); + bool isWrite(kvm_run.io.direction == KVM_EXIT_IO_OUT); unsigned char *guestData(getGuestData(kvm_run.io.data_offset)); Tick delay(0); - uint16_t port(kvm_run.io.port); + Addr pAddr; const int count(kvm_run.io.count); @@ -1367,6 +1376,70 @@ } Tick +X86KvmCPU::handleKvmExitSysCall() +{ + /** updating the thread context with vCPU state */ + updateThreadContext(); + + struct kvm_regs regs; + getRegisters(regs); + + /** restoring rdx from r11 + * the syscall handler uses r11 to + * temporarly store rdx + */ + regs.rdx = tc->readIntReg(INTREG_R11); + tc->setIntReg(INTREG_RDX, regs.rdx); + + /** emulating system call */ + thread->syscall(regs.rax); + + /** updating vCPU's rax, rflags and r11 */ + regs.rax = tc->readIntReg(INTREG_RAX); + regs.rflags &= ~(1<<16); + regs.r11 = regs.rflags; + + setRegisters(regs); + + /** updating vCPU's special registers + * some syscalls update segemnt descriptors + */ + updateKvmStateSRegs(); + + if (DTRACE(KvmContext)) + dump(); + + return 0; +} + +Tick +X86KvmCPU::handleKvmExitPageFault() +{ + struct kvm_sregs sregs; + getSpecialRegisters(sregs); + + Process *p = tc->getProcessPtr(); + if ( p->fixupStackFault(sregs.cr2) ) { + uint64_t IST[10]; + + PortProxy physProxy = system->physProxy; + physProxy.readBlob(ISTPhysAddr + VMPageSize - sizeof(IST), + (uint8_t *)(&IST), sizeof(IST)); + + DPRINTF(Kvm, "IST: %#x %#x %#x %#x %#x %#x %#x %#x %#x %#x\n", + IST[0], IST[1], IST[2], IST[3], IST[4], + IST[5], IST[6], IST[7], IST[8], IST[9]); + + if (DTRACE(KvmContext)) + dump(); + } else { + panic("Page fault at %#x ", sregs.cr2); + } + + return 0; +} + +Tick X86KvmCPU::handleKvmExitIRQWindowOpen() { // We don't need to do anything here since this is caught the next