RE: [PATCH v3] KVM: x86: INIT and reset sequences are different

2015-10-09 Thread Zhang, Yang Z
Paolo Bonzini wrote on 2015-10-01:

Hi Paolo

Sorry for the late reply. I am just back from vacation.

> 
> 
> On 13/04/2015 13:34, Nadav Amit wrote:
>> x86 architecture defines differences between the reset and INIT
>> sequences. INIT does not initialize the FPU (including MMX, XMM, YMM,
>> etc.), TSC, PMU, MSRs (in general), MTRRs machine-check, APIC ID, APIC
>> arbitration ID and BSP.
>> 
>> References (from Intel SDM):
>> 
>> "If the MP protocol has completed and a BSP is chosen, subsequent INITs
>> (either to a specific processor or system wide) do not cause the MP
>> protocol to be repeated." [8.4.2: MP Initialization Protocol
>> Requirements and Restrictions]
>> 
>> [Table 9-1. IA-32 Processor States Following Power-up, Reset, or INIT]
>> 
>> "If the processor is reset by asserting the INIT# pin, the x87 FPU state is 
>> not
>> changed." [9.2: X87 FPU INITIALIZATION]
>> 
>> "The state of the local APIC following an INIT reset is the same as it is 
>> after
>> a power-up or hardware reset, except that the APIC ID and arbitration ID
>> registers are not affected." [10.4.7.3: Local APIC State After an INIT Reset
>> (“Wait-for-SIPI” State)]
>> 
>> Signed-off-by: Nadav Amit 
>> 
>> ---
>> 
>> v3:
>> 
>> - Leave EFER unchanged on INIT. Instead, set cr0 correctly so vmx_set_cr0
> would
>>   recognize that paging was changed from on to off and clear LMA.
> 
> I wonder if this change from v2 to v3 was correct.
> 
> It means that a 32-bit firmware cannot enter paging mode without
> clearing EFER.LME first (which it should not know about).
> 
> Yang, can you check what real hardware does to EFER on an INIT?  Perhaps
> it only clears EFER.LME (in addition of course to EFER.LMA, which is
> cleared as a side effect of writing CR0).

Sure, I will check it with our hardware expert.

> 
> Thanks,
> 
> Paolo


Best regards,
Yang



Re: [PATCH v3] KVM: x86: INIT and reset sequences are different

2015-10-01 Thread Paolo Bonzini


On 13/04/2015 13:34, Nadav Amit wrote:
> x86 architecture defines differences between the reset and INIT sequences.
> INIT does not initialize the FPU (including MMX, XMM, YMM, etc.), TSC, PMU,
> MSRs (in general), MTRRs machine-check, APIC ID, APIC arbitration ID and BSP.
> 
> References (from Intel SDM):
> 
> "If the MP protocol has completed and a BSP is chosen, subsequent INITs 
> (either
> to a specific processor or system wide) do not cause the MP protocol to be
> repeated." [8.4.2: MP Initialization Protocol Requirements and Restrictions]
> 
> [Table 9-1. IA-32 Processor States Following Power-up, Reset, or INIT]
> 
> "If the processor is reset by asserting the INIT# pin, the x87 FPU state is 
> not
> changed." [9.2: X87 FPU INITIALIZATION]
> 
> "The state of the local APIC following an INIT reset is the same as it is 
> after
> a power-up or hardware reset, except that the APIC ID and arbitration ID
> registers are not affected." [10.4.7.3: Local APIC State After an INIT Reset
> (“Wait-for-SIPI” State)]
> 
> Signed-off-by: Nadav Amit 
> 
> ---
> 
> v3:
> 
> - Leave EFER unchanged on INIT. Instead, set cr0 correctly so vmx_set_cr0 
> would
>   recognize that paging was changed from on to off and clear LMA.

I wonder if this change from v2 to v3 was correct.

It means that a 32-bit firmware cannot enter paging mode without
clearing EFER.LME first (which it should not know about).

Yang, can you check what real hardware does to EFER on an INIT?  Perhaps
it only clears EFER.LME (in addition of course to EFER.LMA, which is
cleared as a side effect of writing CR0).

Thanks,

Paolo
--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v3] KVM: x86: INIT and reset sequences are different

2015-04-13 Thread Paolo Bonzini


On 13/04/2015 13:34, Nadav Amit wrote:
 x86 architecture defines differences between the reset and INIT sequences.
 INIT does not initialize the FPU (including MMX, XMM, YMM, etc.), TSC, PMU,
 MSRs (in general), MTRRs machine-check, APIC ID, APIC arbitration ID and BSP.
 
 References (from Intel SDM):
 
 If the MP protocol has completed and a BSP is chosen, subsequent INITs 
 (either
 to a specific processor or system wide) do not cause the MP protocol to be
 repeated. [8.4.2: MP Initialization Protocol Requirements and Restrictions]
 
 [Table 9-1. IA-32 Processor States Following Power-up, Reset, or INIT]
 
 If the processor is reset by asserting the INIT# pin, the x87 FPU state is 
 not
 changed. [9.2: X87 FPU INITIALIZATION]
 
 The state of the local APIC following an INIT reset is the same as it is 
 after
 a power-up or hardware reset, except that the APIC ID and arbitration ID
 registers are not affected. [10.4.7.3: Local APIC State After an INIT Reset
 (“Wait-for-SIPI” State)]
 
 Signed-off-by: Nadav Amit na...@cs.technion.ac.il
 
 ---
 
 v3:
 
 - Leave EFER unchanged on INIT. Instead, set cr0 correctly so vmx_set_cr0 
 would
   recognize that paging was changed from on to off and clear LMA.
 - Clean the surrounding from unnecassary indirection of vmx-vcpu.
 - Change svm similarly to vmx (UNTESTED).

Thanks, applied (locally) for 4.2.  It will take a few weeks before it
gets to kvm/next and in the meanwhile I'll make sure to test on SVM as
well, and to integrate the kvm-unit-tests patches.

Paolo

 v2:
 
 - Same as v1 (was part of a patch-set that was modified due to missing tests)
 ---
  arch/x86/include/asm/kvm_host.h |  6 ++---
  arch/x86/kvm/lapic.c| 11 +
  arch/x86/kvm/lapic.h|  2 +-
  arch/x86/kvm/svm.c  | 27 +++---
  arch/x86/kvm/vmx.c  | 51 
 +++--
  arch/x86/kvm/x86.c  | 17 --
  6 files changed, 63 insertions(+), 51 deletions(-)
 
 diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
 index f80ad59..3a19e30 100644
 --- a/arch/x86/include/asm/kvm_host.h
 +++ b/arch/x86/include/asm/kvm_host.h
 @@ -711,7 +711,7 @@ struct kvm_x86_ops {
   /* Create, but do not attach this VCPU */
   struct kvm_vcpu *(*vcpu_create)(struct kvm *kvm, unsigned id);
   void (*vcpu_free)(struct kvm_vcpu *vcpu);
 - void (*vcpu_reset)(struct kvm_vcpu *vcpu);
 + void (*vcpu_reset)(struct kvm_vcpu *vcpu, bool init_event);
  
   void (*prepare_guest_switch)(struct kvm_vcpu *vcpu);
   void (*vcpu_load)(struct kvm_vcpu *vcpu, int cpu);
 @@ -1001,7 +1001,7 @@ void kvm_pic_clear_all(struct kvm_pic *pic, int 
 irq_source_id);
  
  void kvm_inject_nmi(struct kvm_vcpu *vcpu);
  
 -int fx_init(struct kvm_vcpu *vcpu);
 +int fx_init(struct kvm_vcpu *vcpu, bool init_event);
  
  void kvm_mmu_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa,
  const u8 *new, int bytes);
 @@ -1145,7 +1145,7 @@ int kvm_cpu_has_injectable_intr(struct kvm_vcpu *v);
  int kvm_cpu_has_interrupt(struct kvm_vcpu *vcpu);
  int kvm_arch_interrupt_allowed(struct kvm_vcpu *vcpu);
  int kvm_cpu_get_interrupt(struct kvm_vcpu *v);
 -void kvm_vcpu_reset(struct kvm_vcpu *vcpu);
 +void kvm_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event);
  void kvm_vcpu_reload_apic_access_page(struct kvm_vcpu *vcpu);
  void kvm_arch_mmu_notifier_invalidate_page(struct kvm *kvm,
  unsigned long address);
 diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
 index fe2d89e..a91fb2f 100644
 --- a/arch/x86/kvm/lapic.c
 +++ b/arch/x86/kvm/lapic.c
 @@ -1557,7 +1557,7 @@ void kvm_lapic_set_base(struct kvm_vcpu *vcpu, u64 
 value)
  
  }
  
 -void kvm_lapic_reset(struct kvm_vcpu *vcpu)
 +void kvm_lapic_reset(struct kvm_vcpu *vcpu, bool init_event)
  {
   struct kvm_lapic *apic;
   int i;
 @@ -1571,7 +1571,8 @@ void kvm_lapic_reset(struct kvm_vcpu *vcpu)
   /* Stop the timer in case it's a reset to an active apic */
   hrtimer_cancel(apic-lapic_timer.timer);
  
 - kvm_apic_set_id(apic, vcpu-vcpu_id);
 + if (!init_event)
 + kvm_apic_set_id(apic, vcpu-vcpu_id);
   kvm_apic_set_version(apic-vcpu);
  
   for (i = 0; i  APIC_LVT_NUM; i++)
 @@ -1713,7 +1714,7 @@ int kvm_create_lapic(struct kvm_vcpu *vcpu)
   APIC_DEFAULT_PHYS_BASE | MSR_IA32_APICBASE_ENABLE);
  
   static_key_slow_inc(apic_sw_disabled.key); /* sw disabled at reset */
 - kvm_lapic_reset(vcpu);
 + kvm_lapic_reset(vcpu, false);
   kvm_iodevice_init(apic-dev, apic_mmio_ops);
  
   return 0;
 @@ -2047,8 +2048,8 @@ void kvm_apic_accept_events(struct kvm_vcpu *vcpu)
   pe = xchg(apic-pending_events, 0);
  
   if (test_bit(KVM_APIC_INIT, pe)) {
 - kvm_lapic_reset(vcpu);
 - kvm_vcpu_reset(vcpu);
 + kvm_lapic_reset(vcpu, true);
 + kvm_vcpu_reset(vcpu, true);