From: Avi Kivity <avi@redhat.com>
To: "Nadav Har'El" <nyh@il.ibm.com>
Cc: kvm@vger.kernel.org
Subject: Re: [PATCH 18/24] Exiting from L2 to L1
Date: Mon, 14 Jun 2010 15:04:08 +0300 [thread overview]
Message-ID: <4C161AB8.4060905@redhat.com> (raw)
In-Reply-To: <201006131231.o5DCVlKB013102@rice.haifa.ibm.com>
On 06/13/2010 03:31 PM, Nadav Har'El wrote:
> This patch implements nested_vmx_vmexit(), called when the nested L2 guest
> exits and we want to run its L1 parent and let it handle this exit.
>
> Note that this will not necessarily be called on every L2 exit. L0 may decide
> to handle a particular exit on its own, without L1's involvement; In that
> case, L0 will handle the exit, and resume running L2, without running L1 and
> without calling nested_vmx_vmexit(). The logic for deciding whether to handle
> a particular exit in L1 or in L0, i.e., whether to call nested_vmx_vmexit(),
> will appear in the next patch.
>
>
>
> +/* prepare_vmcs_12 is called when the nested L2 guest exits and we want to
> + * prepare to run its L1 parent. L1 keeps a vmcs for L2 (vmcs12), and this
> + * function updates it to reflect the state of the registers during the exit,
> + * and to reflect some changes that happened while L2 was running (and perhaps
> + * made some exits which were handled directly by L0 without going back to L1).
> + */
> +void prepare_vmcs_12(struct kvm_vcpu *vcpu)
> +{
> + struct shadow_vmcs *vmcs12 = get_shadow_vmcs(vcpu);
> +
> + vmcs12->guest_es_selector = vmcs_read16(GUEST_ES_SELECTOR);
> + vmcs12->guest_cs_selector = vmcs_read16(GUEST_CS_SELECTOR);
> + vmcs12->guest_ss_selector = vmcs_read16(GUEST_SS_SELECTOR);
> + vmcs12->guest_ds_selector = vmcs_read16(GUEST_DS_SELECTOR);
> + vmcs12->guest_fs_selector = vmcs_read16(GUEST_FS_SELECTOR);
> + vmcs12->guest_gs_selector = vmcs_read16(GUEST_GS_SELECTOR);
> + vmcs12->guest_ldtr_selector = vmcs_read16(GUEST_LDTR_SELECTOR);
> + vmcs12->guest_tr_selector = vmcs_read16(GUEST_TR_SELECTOR);
> +
> + vmcs12->tsc_offset = vmcs_read64(TSC_OFFSET);
>
TSC_OFFSET cannot have changed.
> + vmcs12->guest_physical_address = vmcs_read64(GUEST_PHYSICAL_ADDRESS);
>
Not available without EPT.
> + vmcs12->vmcs_link_pointer = vmcs_read64(VMCS_LINK_POINTER);
>
Can this change?
> + vmcs12->guest_ia32_debugctl = vmcs_read64(GUEST_IA32_DEBUGCTL);
>
Without msr bitmaps, cannot change.
> + if (vmcs_config.vmentry_ctrl& VM_ENTRY_LOAD_IA32_PAT)
> + vmcs12->guest_ia32_pat = vmcs_read64(GUEST_IA32_PAT);
>
Should check for VM_EXIT_SAVE_IA32_PAT, no? Also unneeded without msr
bitmaps and passthrough for this msr.
> + vmcs12->cr3_target_count = vmcs_read32(CR3_TARGET_COUNT);
>
R/O
> + vmcs12->vm_entry_intr_info_field =
> + vmcs_read32(VM_ENTRY_INTR_INFO_FIELD);
>
Autocleared, no need to read.
> + vmcs12->vm_entry_exception_error_code =
> + vmcs_read32(VM_ENTRY_EXCEPTION_ERROR_CODE);
> + vmcs12->vm_entry_instruction_len =
> + vmcs_read32(VM_ENTRY_INSTRUCTION_LEN);
>
R/O
> + vmcs12->vm_instruction_error = vmcs_read32(VM_INSTRUCTION_ERROR);
>
We don't want to pass this to the guest?
> + vmcs12->vm_exit_reason = vmcs_read32(VM_EXIT_REASON);
> + vmcs12->vm_exit_intr_info = vmcs_read32(VM_EXIT_INTR_INFO);
> + vmcs12->vm_exit_intr_error_code = vmcs_read32(VM_EXIT_INTR_ERROR_CODE);
> + vmcs12->idt_vectoring_info_field =
> + vmcs_read32(IDT_VECTORING_INFO_FIELD);
> + vmcs12->idt_vectoring_error_code =
> + vmcs_read32(IDT_VECTORING_ERROR_CODE);
> + vmcs12->vm_exit_instruction_len = vmcs_read32(VM_EXIT_INSTRUCTION_LEN);
> + vmcs12->vmx_instruction_info = vmcs_read32(VMX_INSTRUCTION_INFO);
>
For the above, if the host handles the exit, we must not clobber guest
fields. A subsequent guest vmread will see the changed values even
though from its point of view a vmexit has not occurred.
But no, that can't happen, since a vmread needs to have a vmexit first
to happen. Still, best to delay this.+
> + /* If any of the CRO_GUEST_HOST_MASK bits are off, the L2 guest may
> + * have changed some cr0 bits without us ever saving them in the shadow
> + * vmcs. So we need to save these changes now.
> + * In the current code, the only GHM bit which can be off is TS (it
> + * will be off when fpu_active and L1 also set it to off).
> + */
> + vmcs12->guest_cr0 = vmcs_readl(GUEST_CR0);
> +
> + /* But this may not be the guest_cr0 that the L1 guest hypervisor
> + * actually thought it was giving its L2 guest. It is possible that
> + * L1 wished to allow its guest to set a cr0 bit directly, but we (L0)
> + * captured this attempt and instead set just the read shadow. If this
> + * is the case, we need copy these read-shadow bits back to guest_cr0,
> + * where L1 believes they already are. Note that we must read the
> + * actual CR0_READ_SHADOW (which is what L0 may have changed), not
> + * vmcs12->cr0_read_shadow (which L1 defined, and we don't
> + * change without being told by L1). Currently, the only bit where
> + * this can happen is TS.
> + */
> + if (!(vcpu->arch.cr0_guest_owned_bits& X86_CR0_TS)
> + && !(vmcs12->cr0_guest_host_mask& X86_CR0_TS))
> + vmcs12->guest_cr0 =
> + (vmcs12->guest_cr0& ~X86_CR0_TS) |
> + (vmcs_readl(CR0_READ_SHADOW)& X86_CR0_TS);
> +
> + vmcs12->guest_cr4 = vmcs_readl(GUEST_CR4);
>
Can't we have the same issue with cr4?
Better to have some helpers to do the common magic, and not encode the
special knowledge about TS into it (make it generic).
> +
> +int switch_back_vmcs(struct kvm_vcpu *vcpu)
> +{
> + struct shadow_vmcs *src = to_vmx(vcpu)->nested.l1_shadow_vmcs;
> +
> + if (enable_vpid&& src->virtual_processor_id != 0)
> + vmcs_write16(VIRTUAL_PROCESSOR_ID, src->virtual_processor_id);
>
IIUC vpids are not exposed to the guest yet? So the VPID should not
change between guest and nested guest.
> +
> + vmcs_write64(IO_BITMAP_A, src->io_bitmap_a);
> + vmcs_write64(IO_BITMAP_B, src->io_bitmap_b);
>
Why change the I/O bitmap?
> +
> + if (cpu_has_vmx_msr_bitmap())
> + vmcs_write64(MSR_BITMAP, src->msr_bitmap);
>
Or the msr bitmap? After all, we're switching the entire vmcs?
> +
> + vmcs_write64(VIRTUAL_APIC_PAGE_ADDR, src->virtual_apic_page_addr);
> +
> + if (vm_need_virtualize_apic_accesses(vcpu->kvm))
> + vmcs_write64(APIC_ACCESS_ADDR,
> + src->apic_access_addr);
> +
> + if (enable_ept) {
> + vmcs_write64(EPT_POINTER, src->ept_pointer);
> + vmcs_write64(GUEST_PDPTR0, src->guest_pdptr0);
> + vmcs_write64(GUEST_PDPTR1, src->guest_pdptr1);
> + vmcs_write64(GUEST_PDPTR2, src->guest_pdptr2);
> + vmcs_write64(GUEST_PDPTR3, src->guest_pdptr3);
> + }
>
A kvm_set_cr3(src->host_cr3) should do all that and more, no?
> +
> + vmcs_write32(PIN_BASED_VM_EXEC_CONTROL, src->pin_based_vm_exec_control);
> + vmcs_write32(CPU_BASED_VM_EXEC_CONTROL, src->cpu_based_vm_exec_control);
> + vmcs_write32(EXCEPTION_BITMAP, src->exception_bitmap);
> + vmcs_write32(PAGE_FAULT_ERROR_CODE_MASK,
> + src->page_fault_error_code_mask);
> + vmcs_write32(PAGE_FAULT_ERROR_CODE_MATCH,
> + src->page_fault_error_code_match);
> + vmcs_write32(VM_EXIT_CONTROLS, src->vm_exit_controls);
> + vmcs_write32(VM_ENTRY_CONTROLS, src->vm_entry_controls);
>
Why write all these? What could have changed them?
> +
> + if (cpu_has_secondary_exec_ctrls())
> + vmcs_write32(SECONDARY_VM_EXEC_CONTROL,
> + src->secondary_vm_exec_control);
> +
> + load_vmcs_common(src);
> +
> + load_vmcs_host_state(to_vmx(vcpu)->nested.l1_shadow_vmcs);
> +
> + return 0;
> +}
> +
> +static int nested_vmx_vmexit(struct kvm_vcpu *vcpu,
> + bool is_interrupt)
> +{
> + struct vcpu_vmx *vmx = to_vmx(vcpu);
> + int efer_offset;
> +
> + if (!vmx->nested.nested_mode) {
> + printk(KERN_INFO "WARNING: %s called but not in nested mode\n",
> + __func__);
> + return 0;
> + }
> +
> + sync_cached_regs_to_vmcs(vcpu);
> +
> + if (!nested_map_current(vcpu)) {
> + printk(KERN_INFO "Error mapping shadow vmcs\n");
> + set_rflags_to_vmx_fail_valid(vcpu);
> + return 1;
> + }
> +
> + prepare_vmcs_12(vcpu);
> + if (is_interrupt)
> + get_shadow_vmcs(vcpu)->vm_exit_reason =
> + EXIT_REASON_EXTERNAL_INTERRUPT;
> +
> + vmx->nested.current_l2_page->launched = vmx->launched;
> + vmx->nested.current_l2_page->cpu = vcpu->cpu;
> +
> + nested_unmap_current(vcpu);
> +
> + vmx->vmcs = vmx->nested.l1_vmcs;
> + vcpu->cpu = vmx->nested.l1_state.cpu;
> + vmx->launched = vmx->nested.l1_state.launched;
> +
> + vmx_vcpu_load(vcpu, get_cpu());
> + put_cpu();
> +
> + vcpu->arch.efer = vmx->nested.l1_state.efer;
> + if ((vcpu->arch.efer& EFER_LMA)&&
> + !(vcpu->arch.efer& EFER_SCE))
> + vcpu->arch.efer |= EFER_SCE;
> +
> + efer_offset = __find_msr_index(vmx, MSR_EFER);
> + if (update_transition_efer(vmx, efer_offset))
> + wrmsrl(MSR_EFER, vmx->guest_msrs[efer_offset].data);
> +
> + /* We're running a regular L1 guest again, so we do the regular KVM
> + * thing: run vmx_set_cr0 with the cr0 bits the guest thinks it has
> + * (this can be figured out by combining its old guest_cr0 and
> + * cr0_read_shadow, using the cr0_guest_host_mask). vmx_set_cr0 might
> + * use slightly different bits on the new guest_cr0 it sets, e.g.,
> + * add TS when !fpu_active.
> + */
> + vmx_set_cr0(vcpu,
> + (vmx->nested.l1_shadow_vmcs->cr0_guest_host_mask&
> + vmx->nested.l1_shadow_vmcs->cr0_read_shadow) |
> + (~vmx->nested.l1_shadow_vmcs->cr0_guest_host_mask&
> + vmx->nested.l1_shadow_vmcs->guest_cr0));
>
Helper wanted.
> +
> + vmx_set_cr4(vcpu, vmx->nested.l1_state.cr4);
> +
>
Again, the kvm_set_crx() versions have more meat.
> + if (enable_ept) {
> + vcpu->arch.cr3 = vmx->nested.l1_shadow_vmcs->guest_cr3;
> + vmcs_write32(GUEST_CR3, vmx->nested.l1_shadow_vmcs->guest_cr3);
> + } else {
> + kvm_set_cr3(vcpu, vmx->nested.l1_state.cr3);
> + }
>
kvm_set_cr3() will load the PDPTRs in the EPT case (correctly in case
the nested guest was able to corrupted the guest's PDPT).
> +
> + if (!nested_map_current(vcpu)) {
> + printk(KERN_INFO "Error mapping shadow vmcs\n");
> + set_rflags_to_vmx_fail_valid(vcpu);
> + return 1;
> + }
> +
> + switch_back_vmcs(vcpu);
> +
> + nested_unmap_current(vcpu);
> +
> + kvm_register_write(vcpu, VCPU_REGS_RSP,
> + vmx->nested.l1_shadow_vmcs->guest_rsp);
> + kvm_register_write(vcpu, VCPU_REGS_RIP,
> + vmx->nested.l1_shadow_vmcs->guest_rip);
> +
> + vmx->nested.nested_mode = 0;
> +
> + /* If we did fpu_activate()/fpu_deactive() during l2's run, we need
> + * to apply the same changes also when running l1. We don't need to
> + * change cr0 here - we already did this above - just the
> + * cr0_guest_host_mask, and exception bitmap.
> + */
> + vmcs_write32(EXCEPTION_BITMAP,
> + (vmx->nested.l1_shadow_vmcs->exception_bitmap&
> + ~(1u<<NM_VECTOR)) |
> + (vcpu->fpu_active ? 0 : (1u<<NM_VECTOR)));
> + vcpu->arch.cr0_guest_owned_bits = (vcpu->fpu_active ? X86_CR0_TS : 0);
> + vmcs_writel(CR0_GUEST_HOST_MASK, ~vcpu->arch.cr0_guest_owned_bits);
> +
> + kvm_mmu_reset_context(vcpu);
> + kvm_mmu_load(vcpu);
>
kvm_mmu_load() unneeded, usually.
> +
> + if (unlikely(vmx->fail)) {
> + vmx->fail = 0;
> + set_rflags_to_vmx_fail_valid(vcpu);
> + } else
> + clear_rflags_cf_zf(vcpu);
> +
> + return 0;
> +}
> +
> static struct kvm_x86_ops vmx_x86_ops = {
> .cpu_has_kvm_support = cpu_has_kvm_support,
> .disabled_by_bios = vmx_disabled_by_bios,
>
I'm probably missing something about the read/write of various vmcs fields.
--
error compiling committee.c: too many arguments to function
next prev parent reply other threads:[~2010-06-14 12:04 UTC|newest]
Thread overview: 147+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-06-13 12:22 [PATCH 0/24] Nested VMX, v5 Nadav Har'El
2010-06-13 12:23 ` [PATCH 1/24] Move nested option from svm.c to x86.c Nadav Har'El
2010-06-14 8:11 ` Avi Kivity
2010-06-15 14:27 ` Nadav Har'El
2010-06-13 12:23 ` [PATCH 2/24] Add VMX and SVM to list of supported cpuid features Nadav Har'El
2010-06-14 8:13 ` Avi Kivity
2010-06-15 14:31 ` Nadav Har'El
2010-06-13 12:24 ` [PATCH 3/24] Implement VMXON and VMXOFF Nadav Har'El
2010-06-14 8:21 ` Avi Kivity
2010-06-16 11:14 ` Nadav Har'El
2010-06-16 11:26 ` Avi Kivity
2010-06-15 20:18 ` Marcelo Tosatti
2010-06-16 7:50 ` Nadav Har'El
2010-06-13 12:24 ` [PATCH 4/24] Allow setting the VMXE bit in CR4 Nadav Har'El
2010-06-15 11:09 ` Gleb Natapov
2010-06-15 14:44 ` Nadav Har'El
2010-06-13 12:25 ` [PATCH 5/24] Introduce vmcs12: a VMCS structure for L1 Nadav Har'El
2010-06-14 8:33 ` Avi Kivity
2010-06-14 8:49 ` Nadav Har'El
2010-06-14 12:35 ` Avi Kivity
2010-06-16 12:24 ` Nadav Har'El
2010-06-16 13:10 ` Avi Kivity
2010-06-22 14:54 ` Nadav Har'El
2010-06-22 16:53 ` Nadav Har'El
2010-06-23 8:07 ` Avi Kivity
2010-08-08 15:09 ` Nadav Har'El
2010-08-10 3:24 ` Avi Kivity
2010-06-23 7:57 ` Avi Kivity
2010-06-23 9:15 ` Alexander Graf
2010-06-23 9:24 ` Avi Kivity
2010-06-23 12:07 ` Nadav Har'El
2010-06-23 12:13 ` Avi Kivity
2010-06-13 12:25 ` [PATCH 6/24] Implement reading and writing of VMX MSRs Nadav Har'El
2010-06-14 8:42 ` Avi Kivity
2010-06-23 8:13 ` Nadav Har'El
2010-06-23 8:24 ` Avi Kivity
2010-06-13 12:26 ` [PATCH 7/24] Understanding guest pointers to vmcs12 structures Nadav Har'El
2010-06-14 8:48 ` Avi Kivity
2010-08-02 12:25 ` Nadav Har'El
2010-08-02 13:38 ` Avi Kivity
2010-06-15 12:14 ` Gleb Natapov
2010-08-01 15:16 ` Nadav Har'El
2010-08-01 15:25 ` Gleb Natapov
2010-08-02 8:57 ` Nadav Har'El
2010-06-13 12:26 ` [PATCH 8/24] Hold a vmcs02 for each vmcs12 Nadav Har'El
2010-06-14 8:57 ` Avi Kivity
2010-07-06 9:50 ` Dong, Eddie
2010-08-02 13:38 ` Nadav Har'El
2010-06-13 12:27 ` [PATCH 9/24] Implement VMCLEAR Nadav Har'El
2010-06-14 9:03 ` Avi Kivity
2010-06-15 13:47 ` Gleb Natapov
2010-06-15 13:50 ` Avi Kivity
2010-06-15 13:54 ` Gleb Natapov
2010-08-05 11:50 ` Nadav Har'El
2010-08-05 11:53 ` Gleb Natapov
2010-08-05 12:01 ` Nadav Har'El
2010-08-05 12:05 ` Avi Kivity
2010-08-05 12:10 ` Nadav Har'El
2010-08-05 12:13 ` Avi Kivity
2010-08-05 12:29 ` Nadav Har'El
2010-08-05 12:03 ` Avi Kivity
2010-07-06 2:56 ` Dong, Eddie
2010-08-03 12:12 ` Nadav Har'El
2010-06-13 12:27 ` [PATCH 10/24] Implement VMPTRLD Nadav Har'El
2010-06-14 9:07 ` Avi Kivity
2010-08-05 11:13 ` Nadav Har'El
2010-06-16 13:36 ` Gleb Natapov
2010-07-06 3:09 ` Dong, Eddie
2010-08-05 11:35 ` Nadav Har'El
2010-06-13 12:28 ` [PATCH 11/24] Implement VMPTRST Nadav Har'El
2010-06-14 9:15 ` Avi Kivity
2010-06-16 13:53 ` Gleb Natapov
2010-06-16 15:33 ` Nadav Har'El
2010-06-13 12:28 ` [PATCH 12/24] Add VMCS fields to the vmcs12 Nadav Har'El
2010-06-14 9:24 ` Avi Kivity
2010-06-16 14:18 ` Gleb Natapov
2010-06-13 12:29 ` [PATCH 13/24] Implement VMREAD and VMWRITE Nadav Har'El
2010-06-14 9:36 ` Avi Kivity
2010-06-16 14:48 ` Gleb Natapov
2010-08-04 13:42 ` Nadav Har'El
2010-08-04 16:09 ` Nadav Har'El
2010-08-04 16:41 ` Avi Kivity
2010-06-16 15:03 ` Gleb Natapov
2010-08-04 11:46 ` Nadav Har'El
2010-06-13 12:29 ` [PATCH 14/24] Prepare vmcs02 from vmcs01 and vmcs12 Nadav Har'El
2010-06-14 11:11 ` Avi Kivity
2010-06-17 8:50 ` Gleb Natapov
2010-07-06 6:25 ` Dong, Eddie
2010-06-13 12:30 ` [PATCH 15/24] Move register-syncing to a function Nadav Har'El
2010-06-13 12:30 ` [PATCH 16/24] Implement VMLAUNCH and VMRESUME Nadav Har'El
2010-06-14 11:41 ` Avi Kivity
2010-09-26 11:14 ` Nadav Har'El
2010-09-26 12:56 ` Avi Kivity
2010-09-26 13:06 ` Nadav Har'El
2010-09-26 13:51 ` Avi Kivity
2010-06-17 10:59 ` Gleb Natapov
2010-09-16 16:06 ` Nadav Har'El
2010-06-13 12:31 ` [PATCH 17/24] No need for handle_vmx_insn function any more Nadav Har'El
2010-06-13 12:31 ` [PATCH 18/24] Exiting from L2 to L1 Nadav Har'El
2010-06-14 12:04 ` Avi Kivity [this message]
2010-09-12 14:05 ` Nadav Har'El
2010-09-12 14:29 ` Avi Kivity
2010-09-12 17:05 ` Nadav Har'El
2010-09-12 17:21 ` Avi Kivity
2010-09-12 19:51 ` Nadav Har'El
2010-09-13 8:48 ` Avi Kivity
2010-09-13 5:53 ` Sheng Yang
2010-09-13 8:52 ` Avi Kivity
2010-09-13 9:01 ` Nadav Har'El
2010-09-13 9:34 ` Avi Kivity
2010-09-14 13:07 ` Nadav Har'El
2010-06-13 12:32 ` [PATCH 19/24] Deciding if L0 or L1 should handle an L2 exit Nadav Har'El
2010-06-14 12:24 ` Avi Kivity
2010-09-16 14:42 ` Nadav Har'El
2010-06-13 12:32 ` [PATCH 20/24] Correct handling of interrupt injection Nadav Har'El
2010-06-14 12:29 ` Avi Kivity
2010-06-14 12:48 ` Avi Kivity
2010-09-16 15:25 ` Nadav Har'El
2010-06-13 12:33 ` [PATCH 21/24] Correct handling of exception injection Nadav Har'El
2010-06-13 12:33 ` [PATCH 22/24] Correct handling of idt vectoring info Nadav Har'El
2010-06-17 11:58 ` Gleb Natapov
2010-09-20 6:37 ` Nadav Har'El
2010-09-20 9:34 ` Gleb Natapov
2010-09-20 10:03 ` Nadav Har'El
2010-09-20 10:11 ` Avi Kivity
2010-09-22 23:15 ` Nadav Har'El
2010-09-26 15:14 ` Avi Kivity
2010-09-26 15:18 ` Gleb Natapov
2010-09-20 10:20 ` Gleb Natapov
2010-06-13 12:34 ` [PATCH 23/24] Handling of CR0.TS and #NM for Lazy FPU loading Nadav Har'El
2010-06-13 12:34 ` [PATCH 24/24] Miscellenous small corrections Nadav Har'El
2010-06-14 12:34 ` [PATCH 0/24] Nested VMX, v5 Avi Kivity
2010-06-14 13:03 ` Nadav Har'El
2010-06-15 10:00 ` Avi Kivity
2010-10-17 12:03 ` Nadav Har'El
2010-10-17 12:10 ` Avi Kivity
2010-10-17 12:39 ` Nadav Har'El
2010-10-17 13:35 ` Avi Kivity
2010-07-09 8:59 ` Dong, Eddie
2010-07-11 8:27 ` Nadav Har'El
2010-07-11 11:05 ` Alexander Graf
2010-07-11 12:49 ` Nadav Har'El
2010-07-11 13:12 ` Avi Kivity
2010-07-11 15:39 ` Nadav Har'El
2010-07-11 15:45 ` Avi Kivity
2010-07-11 13:20 ` Avi Kivity
2010-07-15 3:27 ` Sheng Yang
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4C161AB8.4060905@redhat.com \
--to=avi@redhat.com \
--cc=kvm@vger.kernel.org \
--cc=nyh@il.ibm.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.