On Wed, 2017-08-02 at 16:32 +0300, Mihai Donțu wrote: > On Wed, 2017-08-02 at 14:27 +0200, Paolo Bonzini wrote: > > On 02/08/2017 13:52, Mihai Donțu wrote: > > > I think it might help to distinguish two situations in which we require > > > the guest _or_ a single vCPU to be paused. Our initial KVMI_PAUSE_GUEST > > > command can be translated into a qemu pause. In our particular usecase > > > we made special arrangements to call it as few times as possible > > > assuming it's very costly. The other is needed only by the internal KVM > > > code for situations similar to: > > > > > > kvm_pause_vcpu(vcpu); > > > vcpu_load(vcpu); > > > kvm_arch_vcpu_ioctl_get_regs(vcpu, regs); > > > vcpu_put(vcpu); > > > kvm_unpause_vcpu(vcpu); > > > > > > or more generally put, for accesses that involve the vCPU state > > > (registers, MSR-s, exceptions etc.), no guest memory involved. > > > > > > Here kvm_pause_vcpu() will only pull the vCPU out of the guest and, if > > > so, make it somehow available for quick re-entry with > > > kvm_unpause_vcpu(). If said vCPU is already out, then the function will > > > be a no-op. Obviously, kvm_{pause,unpause}_vcpu() will do nothing if > > > we're currently handling an event or one is pending. > > > > Understood. The issue is that there is an inherent race between > > anything userspace is doing and get_regs. What are the cases where you > > need to get regs or similar outside an event? > > We have currently identified three cases: > > * initial hooking of a guest > * periodically checking the integrity of data that is not properly > placed into a page and thus cannot be efficiently tracked via SPT > * injecting processes A few more details are required here, taken from our current application: cases (a) and (c) involve poking the vCPU-s a couple of times before doing KVMI_PAUSE_GUEST() after which everything should be OK, though we should make sure qemu sync-s the states before entering the paused state. Case (b), as far as I can see, is implemented only via memory maps (eg. the IDT is mapped and kept around for quick checking), but a need _might_ arrise to poke the vCPU a few times before concluding that an area has really been corrupted. > > > One exception that might have a better solution is: > > > > > > kvm_pause_all_vcpus(kvm); > > > kvm_set_page_access(kvm, gfn); /* pause for get too? */ > > > kvm_unpause_all_vcpus(kvm); > > > > > > There might be a way to make the change and then IPI all vCPU-s without > > > pulling them out of the guest. > > > > For that I think KVMI should define a VM-wide "mask" layered over the > > actual memory map permissions. Such a command can be implemented > > relatively easily by hooking into the callers of __gfn_to_pfn_memslot > > and kvm_vcpu_gfn_to_hva_prot. -- Mihai Donțu