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);