Skip to contentSkip to conversation

qemu support for kvm cpu freq hypercalls

PATCH New Marcelo Tosatti 1 participant 3 messages Feb 2, 2017 KVM

lore
Share & tools
lore
#0 lore raw

cover qemu support for kvm cpu freq hypercalls

Add a new cpu flag to allow vCPUs to perform frequency change hypercalls from userspace.

See the kernel patchseries for more details.

#1 lore raw

PATCH 1/2 kvm: sync linux headers

Sync linux headers.

---
 linux-headers/asm-x86/kvm.h      |    5 +++++
 linux-headers/asm-x86/kvm_para.h |   13 ++++++++++++-
 linux-headers/linux/kvm.h        |    8 ++++++--
 linux-headers/linux/kvm_para.h   |    7 +++++++
 4 files changed, 30 insertions(+), 3 deletions(-)
linux-headers/asm-x86/kvm.h +5 -0
Index: qemu/linux-headers/asm-x86/kvm.h
===================================================================
@@ -357,4 +357,9 @@
 #define KVM_X86_QUIRK_LINT0_REENABLED	(1 << 0)
 #define KVM_X86_QUIRK_CD_NW_CLEARED	(1 << 1)
 
+struct kvm_vcpu_allow_freq {
+	__u16 enable;
+	__u16 pad[7];
+};
+
 #endif /* _ASM_X86_KVM_H */
linux-headers/asm-x86/kvm_para.h +12 -1
Index: qemu/linux-headers/asm-x86/kvm_para.h
===================================================================
@@ -45,7 +45,18 @@
 	__u64 steal;
 	__u32 version;
 	__u32 flags;
-	__u32 pad[12];
+	__u8  preempted;
+	__u8  u8_pad[3];
+	__u32 pad[11];
+};
+
+#define KVM_CLOCK_PAIRING_WALLCLOCK 0
+struct kvm_clock_pairing {
+	__s64 sec;
+	__s64 nsec;
+	__u64 tsc;
+	__u32 flags;
+	__u32 pad[9];
 };
 
 #define KVM_STEAL_ALIGNMENT_BITS 5
linux-headers/linux/kvm.h +6 -2
Index: qemu/linux-headers/linux/kvm.h
===================================================================
@@ -651,6 +651,9 @@
 };
 
 /* for KVM_PPC_GET_PVINFO */
+
+#define KVM_PPC_PVINFO_FLAGS_EV_IDLE   (1<<0)
+
 struct kvm_ppc_pvinfo {
 	/* out */
 	__u32 flags;
@@ -682,8 +685,6 @@
 	struct kvm_ppc_one_seg_page_size sps[KVM_PPC_PAGE_SIZES_MAX_SZ];
 };
 
-#define KVM_PPC_PVINFO_FLAGS_EV_IDLE   (1<<0)
-
 #define KVMIO 0xAE
 
 /* machine type bits, to be used as argument to KVM_CREATE_VM */
@@ -870,6 +871,7 @@
 #define KVM_CAP_S390_USER_INSTR0 130
 #define KVM_CAP_MSI_DEVID 131
 #define KVM_CAP_PPC_HTM 132
+#define KVM_CAP_ALLOW_FREQ_HC 133
 
 #ifdef KVM_CAP_IRQ_ROUTING
 
@@ -1280,6 +1282,8 @@
 #define KVM_S390_GET_IRQ_STATE	  _IOW(KVMIO, 0xb6, struct kvm_s390_irq_state)
 /* Available with KVM_CAP_X86_SMM */
 #define KVM_SMI                   _IO(KVMIO,   0xb7)
+#define KVM_SET_VCPU_ALLOW_FREQ_HC   _IO(KVMIO,   0xb8)
+#define KVM_GET_VCPU_ALLOW_FREQ_HC   _IO(KVMIO,   0xb9)
 
 #define KVM_DEV_ASSIGN_ENABLE_IOMMU	(1 << 0)
 #define KVM_DEV_ASSIGN_PCI_2_3		(1 << 1)
linux-headers/linux/kvm_para.h +7 -0
Index: qemu/linux-headers/linux/kvm_para.h
===================================================================
@@ -14,6 +14,7 @@
 #define KVM_EFAULT		EFAULT
 #define KVM_E2BIG		E2BIG
 #define KVM_EPERM		EPERM
+#define KVM_EOPNOTSUPP		95
 
 #define KVM_HC_VAPIC_POLL_IRQ		1
 #define KVM_HC_MMU_OP			2
@@ -23,6 +24,12 @@
 #define KVM_HC_MIPS_GET_CLOCK_FREQ	6
 #define KVM_HC_MIPS_EXIT_VM		7
 #define KVM_HC_MIPS_CONSOLE_OUTPUT	8
+#define KVM_HC_CLOCK_PAIRING		9
+#define KVM_HC_FREQ_UP			10
+#define KVM_HC_FREQ_DOWN		11
+#define KVM_HC_FREQ_MAX			12
+#define KVM_HC_FREQ_MIN			13
+
 
 /*
  * hypercalls use architecture specific
#2 lore raw

PATCH 2/2 kvm: introduce cpu flag to enable cpu frequency changes via hypercall

In reply to Marcelo Tosatti

Guests with DPDK, whose vcpus run isolated on physical CPUs, want to control the frequency of such physical CPUs.

Introduce a allow-freq-hc CPU flag to enable such hypercalls.

---
 target/i386/cpu.c      |    1 +
 target/i386/cpu.h      |    6 ++++++
 target/i386/kvm.c      |   29 +++++++++++++++++++++++++++++
 target/i386/kvm_i386.h |    1 +
 4 files changed, 37 insertions(+)
target/i386/cpu.c +1 -0
Index: qemu/target/i386/cpu.c
===================================================================
@@ -3659,6 +3659,7 @@
     DEFINE_PROP_BOOL("lmce", X86CPU, enable_lmce, false),
     DEFINE_PROP_BOOL("l3-cache", X86CPU, enable_l3_cache, true),
     DEFINE_PROP_BOOL("vmware-cpuid-freq", X86CPU, vmware_cpuid_freq, true),
+    DEFINE_PROP_BOOL("allow-freq-hc", X86CPU, allow_freq_hc, false),
     DEFINE_PROP_END_OF_LIST()
 };
 
target/i386/cpu.h +6 -0
Index: qemu/target/i386/cpu.h
===================================================================
@@ -1243,6 +1243,12 @@
      */
     bool enable_l3_cache;
 
+    /* Direct frequency hypercalls from guest userspace can be
+     * enabled/disabled via cpu option 'allow_freq_hc=on/off'.
+     * It is disabled by default.
+     */
+    bool allow_freq_hc;
+
     /* Compatibility bits for old machine types: */
     bool enable_cpuid_0xb;
 
target/i386/kvm.c +29 -0
Index: qemu/target/i386/kvm.c
===================================================================
@@ -163,6 +163,11 @@
              has_x2apic_api);
 }
 
+bool kvm_has_allow_freq_hc(void)
+{
+    return kvm_check_extension(kvm_state, KVM_CAP_ALLOW_FREQ_HC);
+}
+
 static int kvm_get_tsc(CPUState *cs)
 {
     X86CPU *cpu = X86_CPU(cs);
@@ -692,6 +697,15 @@
     return 0;
 }
 
+static int kvm_set_vcpu_allow_freq(X86CPU *cpu)
+{
+    struct kvm_vcpu_allow_freq fr;
+
+    fr.enable = 1;
+
+    return kvm_vcpu_ioctl(CPU(cpu), KVM_SET_VCPU_ALLOW_FREQ_HC, &fr);
+}
+
 static Error *invtsc_mig_blocker;
 
 #define KVM_MAX_CPUID_ENTRIES  100
@@ -1040,6 +1054,21 @@
         has_msr_tsc_aux = false;
     }
 
+    if (cpu->allow_freq_hc) {
+        int ret;
+
+        if (!kvm_has_allow_freq_hc()) {
+            error_report("kvm: allow freq hypercall not supported");
+            return -ENOTSUP;
+        }
+
+        ret = kvm_set_vcpu_allow_freq(cpu);
+        if (ret) {
+            error_report("kvm: kvm_set_allow_freq failure, ret=%d", ret);
+            return ret;
+        }
+    }
+
     return 0;
 
  fail:
target/i386/kvm_i386.h +1 -0
Index: qemu/target/i386/kvm_i386.h
===================================================================
@@ -21,6 +21,7 @@
 void kvm_synchronize_all_tsc(void);
 void kvm_arch_reset_vcpu(X86CPU *cs);
 void kvm_arch_do_init_vcpu(X86CPU *cs);
+bool kvm_has_allow_freq_hc(void);
 
 int kvm_device_pci_assign(KVMState *s, PCIHostDeviceAddress *dev_addr,
                           uint32_t flags, uint32_t *dev_id);