diff --git a/kvm.c b/kvm.c index 9a729de..c9c0212 100644 --- a/kvm.c +++ b/kvm.c @@ -314,6 +314,7 @@ #include #include #include +#include #include "kvm_bitops.h" #include "kvm_vmx.h" @@ -2536,6 +2537,11 @@ kvm_ioctl(dev_t dev, int cmd, intptr_t arg, int md, cred_t *cr, int *rv) break; } + if (copyin(argp, &chip, sizeof (chip)) != 0) { + rval = EFAULT; + break; + } + rval = kvm_vm_ioctl_get_irqchip(kvmp, &chip); if (rval == 0 && copyout(&chip, argp, sz) != 0) { @@ -2587,6 +2593,49 @@ kvm_ioctl(dev_t dev, int cmd, intptr_t arg, int md, cred_t *cr, int *rv) rval = kvm_vm_ioctl_get_dirty_log(kvmp, &log); break; } + case KVM_SET_CLOCK: { + struct kvm *kvmp; + struct kvm_clock_data user_ns; + hrtime_t now_ns; + + rval = 0; + if (copyin(argp, &user_ns, sizeof (user_ns)) != 0) { + rval = EFAULT; + break; + } + if ((kvmp = ksp->kds_kvmp) == NULL) { + rval = EINVAL; + break; + } + if (user_ns.clock > INT64_MAX) { + /* refuse value that cannot be converted to hrtime_t */ + rval = EINVAL; + break; + } + + now_ns = gethrtime(); + kvmp->arch.boot_hrtime = now_ns - (hrtime_t)user_ns.clock; + break; + } + case KVM_GET_CLOCK: { + struct kvm *kvmp; + struct kvm_clock_data user_ns; + hrtime_t now_ns; + + if ((kvmp = ksp->kds_kvmp) == NULL) { + rval = EINVAL; + break; + } + + now_ns = gethrtime(); + user_ns.clock = (uint64_t)(now_ns - kvmp->arch.boot_hrtime); + user_ns.flags = 0; + + rval = 0; + if (copyout(&user_ns, argp, sizeof (user_ns)) != 0) + rval = EFAULT; + break; + } case KVM_NMI: { if (ksp->kds_kvmp == NULL) { diff --git a/kvm_emulate.c b/kvm_emulate.c index eb1c803..e1558e6 100644 --- a/kvm_emulate.c +++ b/kvm_emulate.c @@ -3030,9 +3030,9 @@ x86_emulate_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops) c->dst.val = (c->d & ByteOp) ? (int8_t) c->src.val : (int16_t) c->src.val; break; - case 0xc0 ... 0xc1: /* xadd */ + case 0xc0 ... 0xc1: /* xadd */ kvm_ringbuf_record(&ctxt->vcpu->kvcpu_ringbuf, - KVM_RINGBUF_TAG_EMUXADD, (uint64_t)c->dst.ptr); + KVM_RINGBUF_TAG_EMUXADD, (uint64_t)c->dst.ptr); emulate_2op_SrcV("add", c->src, c->dst, ctxt->eflags); /* Write back the register source. */ c->src.val = c->dst.orig_val; diff --git a/kvm_x86.c b/kvm_x86.c index 622198a..eccd75b 100644 --- a/kvm_x86.c +++ b/kvm_x86.c @@ -757,6 +757,8 @@ kvm_write_guest_time(struct kvm_vcpu *v) membar_producer(); + DTRACE_PROBE1(kvm_write_pvclock, struct pvclock_vcpu_time_info *, pvclock); + /* indicate update finished */ pvclock->version = version + 1; vcpu->time_update = hrt; @@ -4786,6 +4788,7 @@ kvm_arch_create_vm(void) /* Record time at boot (creation) */ gethrestime(&kvm->arch.boot_wallclock); + kvm->arch.boot_hrtime = gethrtime(); return (kvm); } diff --git a/kvm_x86host.h b/kvm_x86host.h index 03ca048..d8181a7 100644 --- a/kvm_x86host.h +++ b/kvm_x86host.h @@ -334,7 +334,7 @@ struct pvclock_vcpu_time_info { typedef struct pvclock_vcpu_time_info pvclock_vcpu_time_info_t; /* Values for pvclock_vcpu_time_info_t`flags: */ -#define PVCLOCK_TSC_STABLE_BIT (1 << 0) +#define PVCLOCK_TSC_STABLE_BIT (1 << 0) typedef struct msi_msg { uint32_t address_lo; /* low 32 bits of msi msg. address */