From: Roger Pau Monne <roger.pau@citrix.com>
To: <xen-devel@lists.xenproject.org>
Cc: Roger Pau Monne <roger.pau@citrix.com>,
Jan Beulich <jbeulich@suse.com>,
Andrew Cooper <andrew.cooper3@citrix.com>, Wei Liu <wl@xen.org>
Subject: [PATCH v4 12/12] x86/vpt: introduce a per-vPT lock
Date: Tue, 20 Apr 2021 16:07:23 +0200 [thread overview]
Message-ID: <20210420140723.65321-13-roger.pau@citrix.com> (raw)
In-Reply-To: <20210420140723.65321-1-roger.pau@citrix.com>
Introduce a per virtual timer lock that replaces the existing per-vCPU
and per-domain vPT locks. Since virtual timers are no longer assigned
or migrated between vCPUs the locking can be simplified to a
in-structure spinlock that protects all the fields.
This requires introducing a helper to initialize the spinlock, and
that could be used to initialize other virtual timer fields in the
future.
Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
---
Changes since v1:
- New in his version.
---
xen/arch/x86/emul-i8254.c | 1 +
xen/arch/x86/hvm/hpet.c | 8 +++++-
xen/arch/x86/hvm/hvm.c | 4 ---
xen/arch/x86/hvm/rtc.c | 1 +
xen/arch/x86/hvm/vlapic.c | 1 +
xen/arch/x86/hvm/vpt.c | 52 ++++++++++++++--------------------
xen/include/asm-x86/hvm/vcpu.h | 3 --
xen/include/asm-x86/hvm/vpt.h | 15 ++--------
8 files changed, 33 insertions(+), 52 deletions(-)
diff --git a/xen/arch/x86/emul-i8254.c b/xen/arch/x86/emul-i8254.c
index 73be4188ad4..a47138cbab7 100644
--- a/xen/arch/x86/emul-i8254.c
+++ b/xen/arch/x86/emul-i8254.c
@@ -484,6 +484,7 @@ void pit_init(struct domain *d, unsigned long cpu_khz)
{
register_portio_handler(d, PIT_BASE, 4, handle_pit_io);
register_portio_handler(d, 0x61, 1, handle_speaker_io);
+ init_periodic_timer(&pit->pt0);
}
pit_reset(d);
diff --git a/xen/arch/x86/hvm/hpet.c b/xen/arch/x86/hvm/hpet.c
index ca94e8b4538..20593c3862d 100644
--- a/xen/arch/x86/hvm/hpet.c
+++ b/xen/arch/x86/hvm/hpet.c
@@ -739,12 +739,18 @@ static void hpet_set(HPETState *h)
void hpet_init(struct domain *d)
{
+ HPETState *h = domain_vhpet(d);
+ unsigned int i;
+
if ( !has_vhpet(d) )
return;
- hpet_set(domain_vhpet(d));
+ hpet_set(h);
register_mmio_handler(d, &hpet_mmio_ops);
d->arch.hvm.params[HVM_PARAM_HPET_ENABLED] = 1;
+
+ for ( i = 0; i < HPET_TIMER_NUM; i++ )
+ init_periodic_timer(&h->pt[i]);
}
void hpet_deinit(struct domain *d)
diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c
index ec4ab1f5199..0498c3b02e2 100644
--- a/xen/arch/x86/hvm/hvm.c
+++ b/xen/arch/x86/hvm/hvm.c
@@ -666,8 +666,6 @@ int hvm_domain_initialise(struct domain *d)
/* need link to containing domain */
d->arch.hvm.pl_time->domain = d;
- rwlock_init(&d->arch.hvm.pl_time->pt_migrate);
-
/* Set the default IO Bitmap. */
if ( is_hardware_domain(d) )
{
@@ -1557,8 +1555,6 @@ int hvm_vcpu_initialise(struct vcpu *v)
hvm_asid_flush_vcpu(v);
- spin_lock_init(&v->arch.hvm.tm_lock);
-
rc = hvm_vcpu_cacheattr_init(v); /* teardown: vcpu_cacheattr_destroy */
if ( rc != 0 )
goto fail1;
diff --git a/xen/arch/x86/hvm/rtc.c b/xen/arch/x86/hvm/rtc.c
index b66ca6f64f1..8c8b4ed4018 100644
--- a/xen/arch/x86/hvm/rtc.c
+++ b/xen/arch/x86/hvm/rtc.c
@@ -821,6 +821,7 @@ void rtc_init(struct domain *d)
init_timer(&s->update_timer, rtc_update_timer, s, smp_processor_id());
init_timer(&s->update_timer2, rtc_update_timer2, s, smp_processor_id());
init_timer(&s->alarm_timer, rtc_alarm_cb, s, smp_processor_id());
+ init_periodic_timer(&s->pt);
register_portio_handler(d, RTC_PORT(0), 2, handle_rtc_io);
diff --git a/xen/arch/x86/hvm/vlapic.c b/xen/arch/x86/hvm/vlapic.c
index 2af24989dd5..5c60bf66584 100644
--- a/xen/arch/x86/hvm/vlapic.c
+++ b/xen/arch/x86/hvm/vlapic.c
@@ -1654,6 +1654,7 @@ int vlapic_init(struct vcpu *v)
return 0;
}
+ init_periodic_timer(&vlapic->pt);
vlapic->pt.source = PTSRC_lapic;
vlapic->regs_page = alloc_domheap_page(v->domain, MEMF_no_owner);
diff --git a/xen/arch/x86/hvm/vpt.c b/xen/arch/x86/hvm/vpt.c
index 6a8d216c7b5..e4ecb98d3a4 100644
--- a/xen/arch/x86/hvm/vpt.c
+++ b/xen/arch/x86/hvm/vpt.c
@@ -125,27 +125,6 @@ static int pt_irq_masked(struct periodic_time *pt)
return 1;
}
-/*
- * Functions which want to modify a particular periodic_time object
- * use pt_{un}lock locking helpers.
- *
- * These users lock whichever vCPU the periodic_time is attached to,
- * but since the vCPU could be modified without holding any lock, they
- * need to take an additional lock that protects against pt->vcpu
- * changing.
- */
-static void pt_lock(struct periodic_time *pt)
-{
- read_lock(&pt->vcpu->domain->arch.hvm.pl_time->pt_migrate);
- spin_lock(&pt->vcpu->arch.hvm.tm_lock);
-}
-
-static void pt_unlock(struct periodic_time *pt)
-{
- spin_unlock(&pt->vcpu->arch.hvm.tm_lock);
- read_unlock(&pt->vcpu->domain->arch.hvm.pl_time->pt_migrate);
-}
-
static void pt_process_missed_ticks(struct periodic_time *pt)
{
s_time_t missed_ticks, now = NOW();
@@ -220,7 +199,7 @@ static void pt_timer_fn(void *data)
void *cb_priv;
unsigned int irq;
- pt_lock(pt);
+ spin_lock(&pt->lock);
v = pt->vcpu;
irq = pt->irq;
@@ -235,7 +214,7 @@ static void pt_timer_fn(void *data)
cb_priv = pt->priv;
}
- pt_unlock(pt);
+ spin_unlock(&pt->lock);
if ( cb )
cb(v, cb_priv);
@@ -247,7 +226,7 @@ static void eoi_callback(struct periodic_time *pt)
time_cb *cb = NULL;
void *cb_priv = NULL;
- pt_lock(pt);
+ spin_lock(&pt->lock);
irq_eoi(pt);
if ( pt->pending_intr_nr && inject_interrupt(pt) )
@@ -258,7 +237,7 @@ static void eoi_callback(struct periodic_time *pt)
v = pt->vcpu;
}
- pt_unlock(pt);
+ spin_unlock(&pt->lock);
if ( cb )
cb(v, cb_priv);
@@ -324,6 +303,11 @@ static bool inject_interrupt(struct periodic_time *pt)
return true;
}
+void init_periodic_timer(struct periodic_time *pt)
+{
+ spin_lock_init(&pt->lock);
+}
+
void create_periodic_time(
struct vcpu *v, struct periodic_time *pt, uint64_t delta,
uint64_t period, uint8_t irq, time_cb *cb, void *data, bool level)
@@ -340,7 +324,7 @@ void create_periodic_time(
destroy_periodic_time(pt);
- write_lock(&v->domain->arch.hvm.pl_time->pt_migrate);
+ spin_lock(&pt->lock);
pt->pending_intr_nr = 0;
@@ -403,18 +387,21 @@ void create_periodic_time(
init_timer(&pt->timer, pt_timer_fn, pt, v->processor);
set_timer(&pt->timer, pt->scheduled);
- write_unlock(&v->domain->arch.hvm.pl_time->pt_migrate);
+ spin_unlock(&pt->lock);
}
void destroy_periodic_time(struct periodic_time *pt)
{
unsigned int gsi;
+ spin_lock(&pt->lock);
/* Was this structure previously initialised by create_periodic_time()? */
if ( pt->vcpu == NULL )
+ {
+ spin_unlock(&pt->lock);
return;
+ }
- pt_lock(pt);
pt->pending_intr_nr = 0;
gsi = pt->irq;
@@ -427,7 +414,7 @@ void destroy_periodic_time(struct periodic_time *pt)
hvm_gsi_unregister_callback(pt->vcpu->domain, gsi, &pt->eoi_cb);
break;
}
- pt_unlock(pt);
+ spin_unlock(&pt->lock);
/*
* pt_timer_fn() can run until this kill_timer() returns. We must do this
@@ -442,10 +429,13 @@ static void pt_resume(struct periodic_time *pt)
time_cb *cb = NULL;
void *cb_priv;
+ spin_lock(&pt->lock);
if ( pt->vcpu == NULL )
+ {
+ spin_unlock(&pt->lock);
return;
+ }
- pt_lock(pt);
if ( pt->pending_intr_nr && inject_interrupt(pt) )
{
pt->pending_intr_nr--;
@@ -453,7 +443,7 @@ static void pt_resume(struct periodic_time *pt)
cb_priv = pt->priv;
v = pt->vcpu;
}
- pt_unlock(pt);
+ spin_unlock(&pt->lock);
if ( cb )
cb(v, cb_priv);
diff --git a/xen/include/asm-x86/hvm/vcpu.h b/xen/include/asm-x86/hvm/vcpu.h
index 9a756964fb0..fe3d0e10426 100644
--- a/xen/include/asm-x86/hvm/vcpu.h
+++ b/xen/include/asm-x86/hvm/vcpu.h
@@ -148,9 +148,6 @@ struct hvm_vcpu {
s64 cache_tsc_offset;
u64 guest_time;
- /* Lock for virtual platform timers. */
- spinlock_t tm_lock;
-
bool flag_dr_dirty;
bool debug_state_latch;
bool single_step;
diff --git a/xen/include/asm-x86/hvm/vpt.h b/xen/include/asm-x86/hvm/vpt.h
index 323afa605e7..5628cff8f7a 100644
--- a/xen/include/asm-x86/hvm/vpt.h
+++ b/xen/include/asm-x86/hvm/vpt.h
@@ -48,6 +48,7 @@ struct periodic_time {
time_cb *cb;
void *priv; /* point back to platform time source */
struct hvm_gsi_eoi_callback eoi_cb; /* EOI callback registration data */
+ spinlock_t lock;
};
@@ -126,19 +127,6 @@ struct pl_time { /* platform time */
struct RTCState vrtc;
struct HPETState vhpet;
struct PMTState vpmt;
- /*
- * Functions which want to modify the vcpu field of the vpt need
- * to hold the global lock (pt_migrate) in write mode together
- * with the per-vcpu locks of the lists being modified. Functions
- * that want to lock a periodic_timer that's possibly on a
- * different vCPU list need to take the lock in read mode first in
- * order to prevent the vcpu field of periodic_timer from
- * changing.
- *
- * Note that two vcpu locks cannot be held at the same time to
- * avoid a deadlock.
- */
- rwlock_t pt_migrate;
/* guest_time = Xen sys time + stime_offset */
int64_t stime_offset;
/* Ensures monotonicity in appropriate timer modes. */
@@ -173,6 +161,7 @@ void create_periodic_time(
struct vcpu *v, struct periodic_time *pt, uint64_t delta,
uint64_t period, uint8_t irq, time_cb *cb, void *data, bool level);
void destroy_periodic_time(struct periodic_time *pt);
+void init_periodic_timer(struct periodic_time *pt);
int pv_pit_handler(int port, int data, int write);
void pit_reset(struct domain *d);
--
2.30.1
prev parent reply other threads:[~2021-04-20 14:15 UTC|newest]
Thread overview: 28+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-04-20 14:07 [PATCH v4 00/12] x86/intr: introduce EOI callbacks and fix vPT Roger Pau Monne
2021-04-20 14:07 ` [PATCH v4 01/12] x86/rtc: drop code related to strict mode Roger Pau Monne
2021-04-29 14:53 ` Jan Beulich
2021-05-03 9:28 ` Roger Pau Monné
2021-05-03 12:26 ` Jan Beulich
2021-05-03 14:47 ` Roger Pau Monné
2021-05-03 14:58 ` Jan Beulich
2021-05-03 15:28 ` Roger Pau Monné
2021-05-03 15:59 ` Jan Beulich
2021-04-20 14:07 ` [PATCH v4 02/12] x86/vlapic: introduce an EOI callback mechanism Roger Pau Monne
2021-04-29 15:48 ` Jan Beulich
2021-04-20 14:07 ` [PATCH v4 03/12] x86/vmsi: use the newly introduced EOI callbacks Roger Pau Monne
2021-04-20 14:07 ` [PATCH v4 04/12] x86/vioapic: switch to use the EOI callback mechanism Roger Pau Monne
2021-04-29 15:51 ` Jan Beulich
2021-04-20 14:07 ` [PATCH v4 05/12] x86/hvm: allowing registering EOI callbacks for GSIs Roger Pau Monne
2021-05-03 15:50 ` Jan Beulich
2021-05-04 10:27 ` Roger Pau Monné
2021-04-20 14:07 ` [PATCH v4 06/12] x86/dpci: move code Roger Pau Monne
2021-04-20 14:07 ` [PATCH v4 07/12] x86/dpci: switch to use a GSI EOI callback Roger Pau Monne
2021-05-04 9:28 ` Jan Beulich
2021-04-20 14:07 ` [PATCH v4 08/12] x86/vpt: switch interrupt injection model Roger Pau Monne
2021-05-04 11:00 ` Jan Beulich
2021-04-20 14:07 ` [PATCH v4 09/12] x86/irq: remove unused parameter from hvm_isa_irq_assert Roger Pau Monne
2021-05-04 11:42 ` Jan Beulich
2021-04-20 14:07 ` [PATCH v4 10/12] x86/irq: drop return value from hvm_ioapic_assert Roger Pau Monne
2021-05-04 11:42 ` Jan Beulich
2021-04-20 14:07 ` [PATCH v4 11/12] x86/vpt: remove vPT timers per-vCPU lists Roger Pau Monne
2021-04-20 14:07 ` Roger Pau Monne [this message]
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=20210420140723.65321-13-roger.pau@citrix.com \
--to=roger.pau@citrix.com \
--cc=andrew.cooper3@citrix.com \
--cc=jbeulich@suse.com \
--cc=wl@xen.org \
--cc=xen-devel@lists.xenproject.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).