Add machine option and QMP commands to configure TSC deadline timer advancement. Signed-off-by: Marcelo Tosatti <mtosatti@xxxxxxxxxx> --- monitor.c | 15 ++++++++++ qapi-schema.json | 29 +++++++++++++++++++ qmp-commands.hx | 48 ++++++++++++++++++++++++++++++++ target-i386/kvm.c | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ vl.c | 4 ++ 5 files changed, 176 insertions(+) Index: qemu.tscdeadline/qapi-schema.json =================================================================== --- qemu.tscdeadline.orig/qapi-schema.json +++ qemu.tscdeadline/qapi-schema.json @@ -3515,3 +3515,32 @@ # Since: 2.1 ## { 'command': 'rtc-reset-reinjection' } + +## +# @set-lapic-tscdeadline-advance +# +# This command sets the TSC deadline timer advancement. +# This value will be subtracted from the expiration time +# of the high resolution timer which emulates +# TSC deadline timer. +# +# Useful to achieve low timer latencies. +# +# Only supported by KVM acceleration. +# +# Since: 2.3 +## +{ 'command': 'set-lapic-tscdeadline-advance', + 'data': { 'advance':'int' } +} + +## +# @get-lapic-tscdeadline-advance +# +# This command gets the TSC deadline timer advancement. +# +# Only supported by KVM acceleration. +# +# Since: 2.3 +## +{ 'command': 'get-lapic-tscdeadline-advance', 'returns': 'int' } Index: qemu.tscdeadline/qmp-commands.hx =================================================================== --- qemu.tscdeadline.orig/qmp-commands.hx +++ qemu.tscdeadline/qmp-commands.hx @@ -3854,3 +3854,51 @@ Move mouse pointer to absolute coordinat <- { "return": {} } EQMP + + { + .name = "set-lapic-tscdeadline-advance", + .args_type = "advance:i", + .mhandler.cmd_new = qmp_marshal_input_set_lapic_tscdeadline_advance, + }, + +SQMP +set-lapic-tscdeadline-advance +----------------------------- + +Set LAPIC tscdeadline timer advancement, in nanoseconds. + +Arguments: + +- "advance": LAPIC tscdeadline timer advancement (json-int) + +Example: + +-> { "execute": "set-lapic-tscdeadline-advance 1000" } +<- { "return": {} } + +EQMP + + { + .name = "get-lapic-tscdeadline-advance", + .args_type = "", + .mhandler.cmd_new = qmp_marshal_input_get_lapic_tscdeadline_advance, + }, + +SQMP +get-lapic-tscdeadline-advance +----------------------------- + +Get LAPIC tscdeadline timer advancement, in nanoseconds. + +Arguments: None. + +returns a json-object with the following information: +- "value" : json-int + +Example: + +-> { "execute": "get-lapic-tscdeadline-advance" } +<- { "return": {1000} } + +EQMP + Index: qemu.tscdeadline/vl.c =================================================================== --- qemu.tscdeadline.orig/vl.c +++ qemu.tscdeadline/vl.c @@ -387,6 +387,10 @@ static QemuOptsList qemu_machine_opts = .name = "iommu", .type = QEMU_OPT_BOOL, .help = "Set on/off to enable/disable Intel IOMMU (VT-d)", + },{ + .name = "lapic-tscdeadline-advance", + .type = QEMU_OPT_NUMBER, + .help = "Set lapic tscdeadline timer advance", }, { /* End of list */ } }, Index: qemu.tscdeadline/target-i386/kvm.c =================================================================== --- qemu.tscdeadline.orig/target-i386/kvm.c +++ qemu.tscdeadline/target-i386/kvm.c @@ -37,6 +37,7 @@ #include "hw/pci/pci.h" #include "migration/migration.h" #include "qapi/qmp/qerror.h" +#include "qmp-commands.h" //#define DEBUG_KVM @@ -84,6 +85,10 @@ static bool has_msr_mtrr; static bool has_msr_architectural_pmu; static uint32_t num_architectural_pmu_counters; +static struct lapic_tscdeadline_advance { + unsigned int advance_ns; +} lapic_tscdeadline_advance; + bool kvm_allows_irq0_override(void) { return !kvm_irqchip_in_kernel() || kvm_has_gsi_routing(); @@ -835,12 +840,32 @@ static int kvm_get_supported_msrs(KVMSta return ret; } +static int kvm_set_lapic_tscdeadline(KVMState *s, uint32_t advance) +{ + struct kvm_tscdeadline_advance adv; + int ret = 0; + + memset(&adv, 0, sizeof(adv)); + + adv.timer_advance = advance; + + ret = kvm_vm_ioctl(s, KVM_SET_TSCDEADLINE_ADVANCE, &adv); + if (ret < 0) { + return ret; + } + + lapic_tscdeadline_advance.advance_ns = advance; + + return ret; +} + int kvm_arch_init(KVMState *s) { uint64_t identity_base = 0xfffbc000; uint64_t shadow_mem; int ret; struct utsname utsname; + uint32_t lapic_advance_ns; ret = kvm_get_supported_msrs(s); if (ret < 0) { @@ -894,9 +919,40 @@ int kvm_arch_init(KVMState *s) return ret; } } + + lapic_advance_ns = qemu_opt_get_number(qemu_get_machine_opts(), + "lapic-tscdeadline-advance", + 0); + if (lapic_advance_ns) { + ret = kvm_set_lapic_tscdeadline(s, lapic_advance_ns); + if (ret) { + fprintf(stderr, "Set tscdeadline advance failed: %s\n", + strerror(-ret)); + return ret; + } + } + + return 0; } +int64_t qmp_get_lapic_tscdeadline_advance(Error **errp) +{ + return lapic_tscdeadline_advance.advance_ns; +} + +void qmp_set_lapic_tscdeadline_advance(int64_t advance, Error **errp) +{ + KVMState *s = kvm_state; + int ret; + + ret = kvm_set_lapic_tscdeadline(s, advance); + if (ret) { + error_setg_errno(errp, ret, "set lapic tscdeadline failed"); + return; + } +} + static void set_v8086_seg(struct kvm_segment *lhs, const SegmentCache *rhs) { lhs->selector = rhs->selector; Index: qemu.tscdeadline/monitor.c =================================================================== --- qemu.tscdeadline.orig/monitor.c +++ qemu.tscdeadline/monitor.c @@ -5447,3 +5447,18 @@ void qmp_rtc_reset_reinjection(Error **e error_set(errp, QERR_FEATURE_DISABLED, "rtc-reset-reinjection"); } #endif + +#if !defined (TARGET_I386) || !defined (CONFIG_KVM) +int64_t qmp_get_lapic_tscdeadline_advance(Error **errp) +{ + error_set(errp, QERR_FEATURE_DISABLED, "get-lapic-tscdeadline-advance"); + + return 0; +} + +void qmp_set_lapic_tscdeadline_advance(int64_t advance, Error **errp) +{ + error_set(errp, QERR_FEATURE_DISABLED, "set-lapic-tscdeadline-advance"); +} +#endif + Index: qemu.tscdeadline/include/hw/boards.h =================================================================== --- qemu.tscdeadline.orig/include/hw/boards.h +++ qemu.tscdeadline/include/hw/boards.h @@ -133,6 +133,7 @@ struct MachineState { bool usb; char *firmware; bool iommu; + int lapi_tscdeadline_advance; ram_addr_t ram_size; ram_addr_t maxram_size; Index: qemu.tscdeadline/qemu-options.hx =================================================================== --- qemu.tscdeadline.orig/qemu-options.hx +++ qemu.tscdeadline/qemu-options.hx @@ -37,7 +37,8 @@ DEF("machine", HAS_ARG, QEMU_OPTION_mach " kvm_shadow_mem=size of KVM shadow MMU\n" " dump-guest-core=on|off include guest memory in a core dump (default=on)\n" " mem-merge=on|off controls memory merge support (default: on)\n" - " iommu=on|off controls emulated Intel IOMMU (VT-d) support (default=off)\n", + " iommu=on|off controls emulated Intel IOMMU (VT-d) support (default=off)\n" + " lapic-tscdeadline-advance=value controls LAPIC tscdeadline timer advancement (default=0)\n", QEMU_ARCH_ALL) STEXI @item -machine [type=]@var{name}[,prop=@var{value}[,...]] @@ -66,6 +67,8 @@ the host, de-duplicates identical memory (enabled by default). @item iommu=on|off Enables or disables emulated Intel IOMMU (VT-d) support. The default is off. +@item lapic-tscdeadline-advance=value +Defines the advancement of LAPIC TSC deadline timer, in nanoseconds. @end table ETEXI Index: qemu.tscdeadline/hw/core/machine.c =================================================================== --- qemu.tscdeadline.orig/hw/core/machine.c +++ qemu.tscdeadline/hw/core/machine.c @@ -72,6 +72,35 @@ static void machine_set_kvm_shadow_mem(O ms->kvm_shadow_mem = value; } +static void machine_get_lapic_tscdeadline_advance(Object *obj, Visitor *v, + void *opaque, + const char *name, + Error **errp) +{ + MachineState *ms = MACHINE(obj); + int64_t value = ms->kvm_shadow_mem; + + visit_type_int(v, &value, name, errp); +} + +static void machine_set_lapic_tscdeadline_advance(Object *obj, Visitor *v, + void *opaque, + const char *name, + Error **errp) +{ + MachineState *ms = MACHINE(obj); + Error *error = NULL; + int64_t value; + + visit_type_int(v, &value, name, &error); + if (error) { + error_propagate(errp, error); + return; + } + + ms->lapi_tscdeadline_advance = value; +} + static char *machine_get_kernel(Object *obj, Error **errp) { MachineState *ms = MACHINE(obj); @@ -299,6 +328,10 @@ static void machine_initfn(Object *obj) machine_get_kvm_shadow_mem, machine_set_kvm_shadow_mem, NULL, NULL, NULL); + object_property_add(obj, "lapic-tscdeadline-advance", "int", + machine_get_lapic_tscdeadline_advance, + machine_set_lapic_tscdeadline_advance, + NULL, NULL, NULL); object_property_add_str(obj, "kernel", machine_get_kernel, machine_set_kernel, NULL); object_property_add_str(obj, "initrd", -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html