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 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.