From: Chao Gao <chao.gao@intel.com>
To: xen-devel@lists.xen.org
Cc: Andrew Cooper <andrew.cooper3@citrix.com>,
Jan Beulich <jbeulich@suse.com>, Chao Gao <chao.gao@intel.com>
Subject: [PATCH v2] x86/vlapic: Don't reset APIC ID when handling INIT signal
Date: Wed, 19 Apr 2017 14:40:52 +0800 [thread overview]
Message-ID: <1492584052-92224-1-git-send-email-chao.gao@intel.com> (raw)
According to SDM "ADVANCED PROGRAMMABLE INTERRUPT CONTROLLER (APIC) ->
"EXTENDED XAPIC (X2APIC)" -> "x2APIC State Transitions", the APIC mode
and APIC ID are preserved when handling INIT signal and a reset places
APIC to xAPIC mode. So there are two problems in current code:
1. Using reset logic (aka vlapic_reset) to handle INIT signal.
2. Forgetting resetting APIC to xAPIC mode in vlapic_reset()
This patch introduces a new function vlapic_do_init() and replaces the
wrongly used vlapic_reset(). Also reset APIC to xAPIC mode in
vlapic_reset().
Note that: LDR is read only in x2APIC mode. Resetting it to zero in x2APIC
mode is unreasonable. This patch also doesn't reset LDR when handling INIT
signal in x2APIC mode.
Signed-off-by: Chao Gao <chao.gao@intel.com>
---
v2:
- rename vlapic_INIT to vlapic_do_init
- reset APIC to xAPIC mode in vlapic_reset()
- constify the struct vcpu in vlapic_reset()
- subject, commit message, comment changes
- properly handle LDR in x2apic mode
---
xen/arch/x86/hvm/vlapic.c | 38 +++++++++++++++++++++++++++++---------
1 file changed, 29 insertions(+), 9 deletions(-)
diff --git a/xen/arch/x86/hvm/vlapic.c b/xen/arch/x86/hvm/vlapic.c
index 2653ba8..6be101f 100644
--- a/xen/arch/x86/hvm/vlapic.c
+++ b/xen/arch/x86/hvm/vlapic.c
@@ -83,6 +83,8 @@ static const unsigned int vlapic_lvt_mask[VLAPIC_LVT_NUM] =
((vlapic_get_reg(vlapic, APIC_LVTT) & APIC_TIMER_MODE_MASK) \
== APIC_TIMER_MODE_TSC_DEADLINE)
+static void vlapic_do_init(struct vlapic *vlapic);
+
static int vlapic_find_highest_vector(const void *bitmap)
{
const uint32_t *word = bitmap;
@@ -281,7 +283,7 @@ static void vlapic_init_sipi_one(struct vcpu *target, uint32_t icr)
rc = vcpu_reset(target);
ASSERT(!rc);
target->fpu_initialised = fpu_initialised;
- vlapic_reset(vcpu_vlapic(target));
+ vlapic_do_init(vcpu_vlapic(target));
domain_unlock(target->domain);
break;
}
@@ -1237,16 +1239,14 @@ bool_t is_vlapic_lvtpc_enabled(struct vlapic *vlapic)
!(vlapic_get_reg(vlapic, APIC_LVTPC) & APIC_LVT_MASKED));
}
-/* Reset the VLPAIC back to its power-on/reset state. */
-void vlapic_reset(struct vlapic *vlapic)
+/* Reset the VLAPIC back to its init state. */
+static void vlapic_do_init(struct vlapic *vlapic)
{
- struct vcpu *v = vlapic_vcpu(vlapic);
int i;
- if ( !has_vlapic(v->domain) )
+ if ( !has_vlapic(vlapic_vcpu(vlapic)->domain) )
return;
- vlapic_set_reg(vlapic, APIC_ID, (v->vcpu_id * 2) << 24);
vlapic_set_reg(vlapic, APIC_LVR, VLAPIC_VERSION);
for ( i = 0; i < 8; i++ )
@@ -1257,7 +1257,12 @@ void vlapic_reset(struct vlapic *vlapic)
}
vlapic_set_reg(vlapic, APIC_ICR, 0);
vlapic_set_reg(vlapic, APIC_ICR2, 0);
- vlapic_set_reg(vlapic, APIC_LDR, 0);
+ /*
+ * LDR is read-only in x2APIC mode. Preserve its value when handling
+ * INIT signal in x2APIC mode.
+ */
+ if ( !vlapic_x2apic_mode(vlapic) )
+ vlapic_set_reg(vlapic, APIC_LDR, 0);
vlapic_set_reg(vlapic, APIC_TASKPRI, 0);
vlapic_set_reg(vlapic, APIC_TMICT, 0);
vlapic_set_reg(vlapic, APIC_TMCCT, 0);
@@ -1275,6 +1280,22 @@ void vlapic_reset(struct vlapic *vlapic)
destroy_periodic_time(&vlapic->pt);
}
+/* Reset the VLAPIC back to its power-on/reset state. */
+void vlapic_reset(struct vlapic *vlapic)
+{
+ const struct vcpu *v = vlapic_vcpu(vlapic);
+
+ if ( !has_vlapic(v->domain) )
+ return;
+
+ vlapic_set_reg(vlapic, APIC_ID, (v->vcpu_id * 2) << 24);
+ vlapic_set_reg(vlapic, APIC_LDR, 0);
+ vlapic_do_init(vlapic);
+
+ vlapic->hw.apic_base_msr &= ~(uint64_t)MSR_IA32_APICBASE_EXTD;
+ vlapic->hw.apic_base_msr |= MSR_IA32_APICBASE_ENABLE;
+}
+
/* rearm the actimer if needed, after a HVM restore */
static void lapic_rearm(struct vlapic *s)
{
@@ -1489,8 +1510,7 @@ int vlapic_init(struct vcpu *v)
vlapic_reset(vlapic);
- vlapic->hw.apic_base_msr = (MSR_IA32_APICBASE_ENABLE |
- APIC_DEFAULT_PHYS_BASE);
+ vlapic->hw.apic_base_msr |= APIC_DEFAULT_PHYS_BASE;
if ( v->vcpu_id == 0 )
vlapic->hw.apic_base_msr |= MSR_IA32_APICBASE_BSP;
--
1.8.3.1
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel
next reply other threads:[~2017-04-19 6:40 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-04-19 6:40 Chao Gao [this message]
2017-04-19 14:17 ` [PATCH v2] x86/vlapic: Don't reset APIC ID when handling INIT signal Jan Beulich
2017-04-19 7:41 ` Chao Gao
2017-04-19 15:04 ` Jan Beulich
2017-04-19 19:33 ` Chao Gao
2017-04-20 9:55 ` Jan Beulich
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=1492584052-92224-1-git-send-email-chao.gao@intel.com \
--to=chao.gao@intel.com \
--cc=andrew.cooper3@citrix.com \
--cc=jbeulich@suse.com \
--cc=xen-devel@lists.xen.org \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).