qemu with hax to log dma reads & writes jcs.org/2018/11/12/vfio

hyperv: qom-ify SynIC

Make Hyper-V SynIC a device which is attached as a child to a CPU. For
now it only makes SynIC visibile in the qom hierarchy, and maintains its
internal fields in sync with the respecitve msrs of the parent cpu (the
fields will be used in followup patches).

Signed-off-by: Roman Kagan <rkagan@virtuozzo.com>
Message-Id: <20180921082217.29481-3-rkagan@virtuozzo.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>

authored by

Roman Kagan and committed by
Paolo Bonzini
606c34bf 729ce7e1

+164 -2
+99 -2
hw/hyperv/hyperv.c
··· 9 9 10 10 #include "qemu/osdep.h" 11 11 #include "qemu/main-loop.h" 12 + #include "qapi/error.h" 12 13 #include "sysemu/kvm.h" 13 14 #include "hw/hyperv/hyperv.h" 14 15 16 + typedef struct SynICState { 17 + DeviceState parent_obj; 18 + 19 + CPUState *cs; 20 + 21 + bool enabled; 22 + hwaddr msg_page_addr; 23 + hwaddr event_page_addr; 24 + } SynICState; 25 + 26 + #define TYPE_SYNIC "hyperv-synic" 27 + #define SYNIC(obj) OBJECT_CHECK(SynICState, (obj), TYPE_SYNIC) 28 + 29 + static SynICState *get_synic(CPUState *cs) 30 + { 31 + return SYNIC(object_resolve_path_component(OBJECT(cs), "synic")); 32 + } 33 + 34 + static void synic_update(SynICState *synic, bool enable, 35 + hwaddr msg_page_addr, hwaddr event_page_addr) 36 + { 37 + 38 + synic->enabled = enable; 39 + synic->msg_page_addr = msg_page_addr; 40 + synic->event_page_addr = event_page_addr; 41 + } 42 + 43 + void hyperv_synic_update(CPUState *cs, bool enable, 44 + hwaddr msg_page_addr, hwaddr event_page_addr) 45 + { 46 + SynICState *synic = get_synic(cs); 47 + 48 + if (!synic) { 49 + return; 50 + } 51 + 52 + synic_update(synic, enable, msg_page_addr, event_page_addr); 53 + } 54 + 55 + static void synic_realize(DeviceState *dev, Error **errp) 56 + { 57 + } 58 + 59 + static void synic_reset(DeviceState *dev) 60 + { 61 + SynICState *synic = SYNIC(dev); 62 + synic_update(synic, false, 0, 0); 63 + } 64 + 65 + static void synic_class_init(ObjectClass *klass, void *data) 66 + { 67 + DeviceClass *dc = DEVICE_CLASS(klass); 68 + 69 + dc->realize = synic_realize; 70 + dc->reset = synic_reset; 71 + dc->user_creatable = false; 72 + } 73 + 74 + void hyperv_synic_add(CPUState *cs) 75 + { 76 + Object *obj; 77 + SynICState *synic; 78 + 79 + obj = object_new(TYPE_SYNIC); 80 + synic = SYNIC(obj); 81 + synic->cs = cs; 82 + object_property_add_child(OBJECT(cs), "synic", obj, &error_abort); 83 + object_unref(obj); 84 + object_property_set_bool(obj, true, "realized", &error_abort); 85 + } 86 + 87 + void hyperv_synic_reset(CPUState *cs) 88 + { 89 + device_reset(DEVICE(get_synic(cs))); 90 + } 91 + 92 + static const TypeInfo synic_type_info = { 93 + .name = TYPE_SYNIC, 94 + .parent = TYPE_DEVICE, 95 + .instance_size = sizeof(SynICState), 96 + .class_init = synic_class_init, 97 + }; 98 + 99 + static void synic_register_types(void) 100 + { 101 + type_register_static(&synic_type_info); 102 + } 103 + 104 + type_init(synic_register_types) 105 + 15 106 struct HvSintRoute { 16 107 uint32_t sint; 17 - CPUState *cs; 108 + SynICState *synic; 18 109 int gsi; 19 110 EventNotifier sint_set_notifier; 20 111 EventNotifier sint_ack_notifier; ··· 46 137 EventNotifier *ack_notifier; 47 138 int r, gsi; 48 139 CPUState *cs; 140 + SynICState *synic; 49 141 50 142 cs = hyperv_find_vcpu(vp_index); 51 143 if (!cs) { 52 144 return NULL; 53 145 } 54 146 147 + synic = get_synic(cs); 148 + if (!synic) { 149 + return NULL; 150 + } 151 + 55 152 sint_route = g_new0(HvSintRoute, 1); 56 153 r = event_notifier_init(&sint_route->sint_set_notifier, false); 57 154 if (r) { ··· 82 179 sint_route->gsi = gsi; 83 180 sint_route->sint_ack_clb = sint_ack_clb; 84 181 sint_route->sint_ack_clb_data = sint_ack_clb_data; 85 - sint_route->cs = cs; 182 + sint_route->synic = synic; 86 183 sint_route->sint = sint; 87 184 sint_route->refcount = 1; 88 185
+5
include/hw/hyperv/hyperv.h
··· 28 28 return cs->cpu_index; 29 29 } 30 30 31 + void hyperv_synic_add(CPUState *cs); 32 + void hyperv_synic_reset(CPUState *cs); 33 + void hyperv_synic_update(CPUState *cs, bool enable, 34 + hwaddr msg_page_addr, hwaddr event_page_addr); 35 + 31 36 #endif
+13
target/i386/hyperv-stub.c
··· 33 33 } 34 34 } 35 35 #endif 36 + 37 + int hyperv_x86_synic_add(X86CPU *cpu) 38 + { 39 + return -ENOSYS; 40 + } 41 + 42 + void hyperv_x86_synic_reset(X86CPU *cpu) 43 + { 44 + } 45 + 46 + void hyperv_x86_synic_update(X86CPU *cpu) 47 + { 48 + }
+25
target/i386/hyperv.c
··· 16 16 #include "hw/hyperv/hyperv.h" 17 17 #include "hyperv-proto.h" 18 18 19 + int hyperv_x86_synic_add(X86CPU *cpu) 20 + { 21 + hyperv_synic_add(CPU(cpu)); 22 + return 0; 23 + } 24 + 25 + void hyperv_x86_synic_reset(X86CPU *cpu) 26 + { 27 + hyperv_synic_reset(CPU(cpu)); 28 + } 29 + 30 + void hyperv_x86_synic_update(X86CPU *cpu) 31 + { 32 + CPUX86State *env = &cpu->env; 33 + bool enable = env->msr_hv_synic_control & HV_SYNIC_ENABLE; 34 + hwaddr msg_page_addr = (env->msr_hv_synic_msg_page & HV_SIMP_ENABLE) ? 35 + (env->msr_hv_synic_msg_page & TARGET_PAGE_MASK) : 0; 36 + hwaddr event_page_addr = (env->msr_hv_synic_evt_page & HV_SIEFP_ENABLE) ? 37 + (env->msr_hv_synic_evt_page & TARGET_PAGE_MASK) : 0; 38 + hyperv_synic_update(CPU(cpu), enable, msg_page_addr, event_page_addr); 39 + } 40 + 19 41 int kvm_hv_handle_exit(X86CPU *cpu, struct kvm_hyperv_exit *exit) 20 42 { 21 43 CPUX86State *env = &cpu->env; ··· 44 66 default: 45 67 return -1; 46 68 } 69 + 70 + hyperv_x86_synic_update(cpu); 71 + 47 72 return 0; 48 73 case KVM_EXIT_HYPERV_HCALL: { 49 74 uint16_t code;
+4
target/i386/hyperv.h
··· 22 22 int kvm_hv_handle_exit(X86CPU *cpu, struct kvm_hyperv_exit *exit); 23 23 #endif 24 24 25 + int hyperv_x86_synic_add(X86CPU *cpu); 26 + void hyperv_x86_synic_reset(X86CPU *cpu); 27 + void hyperv_x86_synic_update(X86CPU *cpu); 28 + 25 29 #endif
+9
target/i386/kvm.c
··· 790 790 strerror(-ret)); 791 791 return ret; 792 792 } 793 + 794 + ret = hyperv_x86_synic_add(cpu); 795 + if (ret < 0) { 796 + error_report("failed to create HyperV SynIC: %s", 797 + strerror(-ret)); 798 + return ret; 799 + } 793 800 } 794 801 795 802 return 0; ··· 1250 1257 for (i = 0; i < ARRAY_SIZE(env->msr_hv_synic_sint); i++) { 1251 1258 env->msr_hv_synic_sint[i] = HV_SINT_MASKED; 1252 1259 } 1260 + 1261 + hyperv_x86_synic_reset(cpu); 1253 1262 } 1254 1263 } 1255 1264
+9
target/i386/machine.c
··· 7 7 #include "hw/i386/pc.h" 8 8 #include "hw/isa/isa.h" 9 9 #include "migration/cpu.h" 10 + #include "hyperv.h" 10 11 11 12 #include "sysemu/kvm.h" 12 13 ··· 672 673 return false; 673 674 } 674 675 676 + static int hyperv_synic_post_load(void *opaque, int version_id) 677 + { 678 + X86CPU *cpu = opaque; 679 + hyperv_x86_synic_update(cpu); 680 + return 0; 681 + } 682 + 675 683 static const VMStateDescription vmstate_msr_hyperv_synic = { 676 684 .name = "cpu/msr_hyperv_synic", 677 685 .version_id = 1, 678 686 .minimum_version_id = 1, 679 687 .needed = hyperv_synic_enable_needed, 688 + .post_load = hyperv_synic_post_load, 680 689 .fields = (VMStateField[]) { 681 690 VMSTATE_UINT64(env.msr_hv_synic_control, X86CPU), 682 691 VMSTATE_UINT64(env.msr_hv_synic_evt_page, X86CPU),