From: Keir Fraser <keir.xen@gmail.com>
To: "Zhang, Yang Z" <yang.z.zhang@intel.com>,
"xen-devel@lists.xen.org" <xen-devel@lists.xen.org>
Cc: "Qiu, Shuang" <shuang.qiu@intel.com>,
"Zhang, Xiantao" <xiantao.zhang@intel.com>,
Jan Beulich <jbeulich@suse.com>
Subject: Re: use tasklet to handle init/sipi?
Date: Tue, 26 Mar 2013 08:02:18 +0000 [thread overview]
Message-ID: <CD77068C.1BBD7%keir.xen@gmail.com> (raw)
In-Reply-To: <CD77050D.1BBD3%keir.xen@gmail.com>
[-- Attachment #1: Type: text/plain, Size: 1604 bytes --]
On 26/03/2013 07:55, "Keir Fraser" <keir.xen@gmail.com> wrote:
> On 26/03/2013 07:41, "Zhang, Yang Z" <yang.z.zhang@intel.com> wrote:
>
>> Keir Fraser wrote on 2013-03-26:
>>> On 26/03/2013 07:17, "Zhang, Yang Z" <yang.z.zhang@intel.com> wrote:
>>>
>>>>>> Oh, I see. Well I think it is fine to have
>>>>>> vlapic_schedule_init_sipi_tasklet() return X86EMUL_OKAY rather than
>>>>>> X86EMUL_RETRY. We used to need to return RETRY, but the code got
>>>>>> simplified and now it is actually unnecessary.
>>>>>>
>>>>>> That should make your patch a lot simpler eh? ;)
>>>>>
>>>>> Given that you ignore the return code on the apicv call path, is there
>>>>> currently a bug at all for you? Seems what is there already must work
>>>>> for you?
>>>> It do cause bug after we change to use seabios. For seabios, it will
>>>> send INIT/SIPI to all vcpus via broadcasting. And there only one vcpu
>>>> is waken up via tasklet with current logic. That's the reason why I
>>>> want to wakeup all vcpus on one callback. Just change X86EMUL_RETRY to
>>>> OK cannot solve the problem. still need the logic I mentioned above.
>>>
>>> Ok, wait a sec, I will sort out a patch for you to try...
>> Thanks. Actually, I have patch on hand and testing it now. But it's ok if you
>> can provide a more better solution.
>
> See how you like it compared with the attached patch. Attached doesn't
> really make the code any more complicated, which is nice. However it is not
> tested, at all. ;)
And here's a version which actually net *reduces* the code size.
-- Keir
> -- Keir
>
>> Best regards,
>> Yang
>>
>>
>
[-- Attachment #2: 01-vlapic-init --]
[-- Type: application/octet-stream, Size: 8647 bytes --]
diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c
index ea7adf6..38e87ce 100644
--- a/xen/arch/x86/hvm/hvm.c
+++ b/xen/arch/x86/hvm/hvm.c
@@ -3461,8 +3461,6 @@ void hvm_vcpu_reset_state(struct vcpu *v, uint16_t cs, uint16_t ip)
struct domain *d = v->domain;
struct segment_register reg;
- BUG_ON(vcpu_runnable(v));
-
domain_lock(d);
if ( v->is_initialised )
diff --git a/xen/arch/x86/hvm/viridian.c b/xen/arch/x86/hvm/viridian.c
index 6c7f2dc..1ee0f7f 100644
--- a/xen/arch/x86/hvm/viridian.c
+++ b/xen/arch/x86/hvm/viridian.c
@@ -240,8 +240,8 @@ int wrmsr_viridian_regs(uint32_t idx, uint64_t val)
eax &= ~(1 << 12);
edx &= 0xff000000;
vlapic_set_reg(vlapic, APIC_ICR2, edx);
- if ( vlapic_ipi(vlapic, eax, edx) == X86EMUL_OKAY )
- vlapic_set_reg(vlapic, APIC_ICR, eax);
+ vlapic_ipi(vlapic, eax, edx);
+ vlapic_set_reg(vlapic, APIC_ICR, eax);
break;
}
diff --git a/xen/arch/x86/hvm/vlapic.c b/xen/arch/x86/hvm/vlapic.c
index 38ff216..d69e8af 100644
--- a/xen/arch/x86/hvm/vlapic.c
+++ b/xen/arch/x86/hvm/vlapic.c
@@ -243,18 +243,22 @@ bool_t vlapic_match_dest(
return 0;
}
-static void vlapic_init_sipi_action(unsigned long _vcpu)
+static void vlapic_init_sipi_one(struct vcpu *target, uint32_t icr)
{
- struct vcpu *origin = (struct vcpu *)_vcpu;
- struct vcpu *target = vcpu_vlapic(origin)->init_sipi.target;
- uint32_t icr = vcpu_vlapic(origin)->init_sipi.icr;
-
vcpu_pause(target);
switch ( icr & APIC_MODE_MASK )
{
case APIC_DM_INIT: {
bool_t fpu_initialised;
+ /* No work on INIT de-assert for P4-type APIC. */
+ if ( (icr & (APIC_INT_LEVELTRIG | APIC_INT_ASSERT)) ==
+ APIC_INT_LEVELTRIG )
+ break;
+ /* Nothing to do if the VCPU is already reset. */
+ if ( !target->is_initialised )
+ break;
+ hvm_vcpu_down(target);
domain_lock(target->domain);
/* Reset necessary VCPU state. This does not include FPU state. */
fpu_initialised = target->fpu_initialised;
@@ -276,36 +280,36 @@ static void vlapic_init_sipi_action(unsigned long _vcpu)
}
vcpu_unpause(target);
-
- vcpu_vlapic(origin)->init_sipi.target = NULL;
- vcpu_unpause(origin);
}
-static int vlapic_schedule_init_sipi_tasklet(struct vcpu *target, uint32_t icr)
+static void vlapic_init_sipi_action(unsigned long _vcpu)
{
- struct vcpu *origin = current;
+ struct vcpu *origin = (struct vcpu *)_vcpu;
+ uint32_t icr = vcpu_vlapic(origin)->init_sipi.icr;
+ uint32_t dest = vcpu_vlapic(origin)->init_sipi.dest;
+ uint32_t short_hand = icr & APIC_SHORT_MASK;
+ uint32_t dest_mode = !!(icr & APIC_DEST_MASK);
+ struct vcpu *v;
+
+ if ( icr == 0 )
+ return;
- if ( vcpu_vlapic(origin)->init_sipi.target != NULL )
+ for_each_vcpu ( origin->domain, v )
{
- WARN(); /* should be impossible but don't BUG, just in case */
- return X86EMUL_UNHANDLEABLE;
+ if ( vlapic_match_dest(vcpu_vlapic(v), vcpu_vlapic(origin),
+ short_hand, dest, dest_mode) )
+ vlapic_init_sipi_one(v, icr);
}
- vcpu_pause_nosync(origin);
-
- vcpu_vlapic(origin)->init_sipi.target = target;
- vcpu_vlapic(origin)->init_sipi.icr = icr;
- tasklet_schedule(&vcpu_vlapic(origin)->init_sipi.tasklet);
-
- return X86EMUL_RETRY;
+ vcpu_vlapic(origin)->init_sipi.icr = 0;
+ vcpu_unpause(origin);
}
/* Add a pending IRQ into lapic. */
-static int vlapic_accept_irq(struct vcpu *v, uint32_t icr_low)
+static void vlapic_accept_irq(struct vcpu *v, uint32_t icr_low)
{
struct vlapic *vlapic = vcpu_vlapic(v);
uint8_t vector = (uint8_t)icr_low;
- int rc = X86EMUL_OKAY;
switch ( icr_low & APIC_MODE_MASK )
{
@@ -339,31 +343,15 @@ static int vlapic_accept_irq(struct vcpu *v, uint32_t icr_low)
break;
case APIC_DM_INIT:
- /* No work on INIT de-assert for P4-type APIC. */
- if ( (icr_low & (APIC_INT_LEVELTRIG | APIC_INT_ASSERT)) ==
- APIC_INT_LEVELTRIG )
- break;
- /* Nothing to do if the VCPU is already reset. */
- if ( !v->is_initialised )
- break;
- hvm_vcpu_down(v);
- rc = vlapic_schedule_init_sipi_tasklet(v, icr_low);
- break;
-
case APIC_DM_STARTUP:
- /* Nothing to do if the VCPU is already initialised. */
- if ( v->is_initialised )
- break;
- rc = vlapic_schedule_init_sipi_tasklet(v, icr_low);
- break;
+ /* Handled in vlapic_ipi(). */
+ BUG();
default:
gdprintk(XENLOG_ERR, "TODO: unsupported delivery mode in ICR %x\n",
icr_low);
domain_crash(v->domain);
}
-
- return rc;
}
struct vlapic *vlapic_lowest_prio(
@@ -421,15 +409,12 @@ void vlapic_handle_EOI_induced_exit(struct vlapic *vlapic, int vector)
hvm_dpci_msi_eoi(current->domain, vector);
}
-int vlapic_ipi(
+void vlapic_ipi(
struct vlapic *vlapic, uint32_t icr_low, uint32_t icr_high)
{
unsigned int dest;
unsigned int short_hand = icr_low & APIC_SHORT_MASK;
unsigned int dest_mode = !!(icr_low & APIC_DEST_MASK);
- struct vlapic *target;
- struct vcpu *v;
- int rc = X86EMUL_OKAY;
HVM_DBG_LOG(DBG_LEVEL_VLAPIC, "icr = 0x%08x:%08x", icr_high, icr_low);
@@ -437,25 +422,40 @@ int vlapic_ipi(
? icr_high
: GET_xAPIC_DEST_FIELD(icr_high));
- if ( (icr_low & APIC_MODE_MASK) == APIC_DM_LOWEST )
+ switch ( icr_low & APIC_MODE_MASK )
{
- target = vlapic_lowest_prio(vlapic_domain(vlapic), vlapic,
- short_hand, dest, dest_mode);
+ case APIC_DM_INIT:
+ case APIC_DM_STARTUP:
+ if ( vlapic->init_sipi.icr != 0 )
+ {
+ WARN(); /* should be impossible but don't BUG, just in case */
+ break;
+ }
+ vcpu_pause_nosync(vlapic_vcpu(vlapic));
+ vlapic->init_sipi.icr = icr_low;
+ vlapic->init_sipi.dest = dest;
+ tasklet_schedule(&vlapic->init_sipi.tasklet);
+ break;
+
+ case APIC_DM_LOWEST: {
+ struct vlapic *target = vlapic_lowest_prio(
+ vlapic_domain(vlapic), vlapic, short_hand, dest, dest_mode);
if ( target != NULL )
- rc = vlapic_accept_irq(vlapic_vcpu(target), icr_low);
- return rc;
+ vlapic_accept_irq(vlapic_vcpu(target), icr_low);
+ break;
}
- for_each_vcpu ( vlapic_domain(vlapic), v )
- {
- if ( vlapic_match_dest(vcpu_vlapic(v), vlapic,
- short_hand, dest, dest_mode) )
- rc = vlapic_accept_irq(v, icr_low);
- if ( rc != X86EMUL_OKAY )
- break;
+ default: {
+ struct vcpu *v;
+ for_each_vcpu ( vlapic_domain(vlapic), v )
+ {
+ if ( vlapic_match_dest(vcpu_vlapic(v), vlapic,
+ short_hand, dest, dest_mode) )
+ vlapic_accept_irq(v, icr_low);
+ }
+ break;
+ }
}
-
- return rc;
}
static uint32_t vlapic_get_tmcct(struct vlapic *vlapic)
@@ -688,9 +688,8 @@ static int vlapic_reg_write(struct vcpu *v,
case APIC_ICR:
val &= ~(1 << 12); /* always clear the pending bit */
- rc = vlapic_ipi(vlapic, val, vlapic_get_reg(vlapic, APIC_ICR2));
- if ( rc == X86EMUL_OKAY )
- vlapic_set_reg(vlapic, APIC_ICR, val);
+ vlapic_ipi(vlapic, val, vlapic_get_reg(vlapic, APIC_ICR2));
+ vlapic_set_reg(vlapic, APIC_ICR, val);
break;
case APIC_ICR2:
diff --git a/xen/include/asm-x86/hvm/vlapic.h b/xen/include/asm-x86/hvm/vlapic.h
index 09cb63c..101ef57 100644
--- a/xen/include/asm-x86/hvm/vlapic.h
+++ b/xen/include/asm-x86/hvm/vlapic.h
@@ -62,8 +62,7 @@ struct vlapic {
struct page_info *regs_page;
/* INIT-SIPI-SIPI work gets deferred to a tasklet. */
struct {
- struct vcpu *target;
- uint32_t icr;
+ uint32_t icr, dest;
struct tasklet tasklet;
} init_sipi;
};
@@ -102,7 +101,7 @@ void vlapic_adjust_i8259_target(struct domain *d);
void vlapic_EOI_set(struct vlapic *vlapic);
void vlapic_handle_EOI_induced_exit(struct vlapic *vlapic, int vector);
-int vlapic_ipi(struct vlapic *vlapic, uint32_t icr_low, uint32_t icr_high);
+void vlapic_ipi(struct vlapic *vlapic, uint32_t icr_low, uint32_t icr_high);
int vlapic_apicv_write(struct vcpu *v, unsigned int offset);
[-- Attachment #3: Type: text/plain, Size: 126 bytes --]
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel
next prev parent reply other threads:[~2013-03-26 8:02 UTC|newest]
Thread overview: 22+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-03-25 5:31 use tasklet to handle init/sipi? Zhang, Yang Z
2013-03-25 6:29 ` Keir Fraser
2013-03-25 6:55 ` Zhang, Yang Z
2013-03-25 8:05 ` Keir Fraser
2013-03-25 12:16 ` Zhang, Yang Z
2013-03-25 12:38 ` Jan Beulich
2013-03-25 12:39 ` Keir Fraser
2013-03-26 3:15 ` Zhang, Yang Z
2013-03-26 6:07 ` Keir Fraser
2013-03-26 6:14 ` Zhang, Yang Z
2013-03-26 7:00 ` Keir Fraser
2013-03-26 7:11 ` Keir Fraser
2013-03-26 7:17 ` Zhang, Yang Z
2013-03-26 7:38 ` Keir Fraser
2013-03-26 7:41 ` Zhang, Yang Z
2013-03-26 7:55 ` Keir Fraser
2013-03-26 8:02 ` Keir Fraser [this message]
2013-03-28 1:18 ` Zhang, Yang Z
2013-03-28 6:39 ` Qiu, Shuang
2013-03-28 11:48 ` Keir Fraser
2013-03-28 15:29 ` Jan Beulich
2013-03-28 20:02 ` Keir Fraser
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=CD77068C.1BBD7%keir.xen@gmail.com \
--to=keir.xen@gmail.com \
--cc=jbeulich@suse.com \
--cc=shuang.qiu@intel.com \
--cc=xen-devel@lists.xen.org \
--cc=xiantao.zhang@intel.com \
--cc=yang.z.zhang@intel.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 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).