xen-devel.lists.xenproject.org archive mirror
 help / color / mirror / Atom feed
From: Keir Fraser <keir@xen.org>
To: "Zhang, Yang Z" <yang.z.zhang@intel.com>,
	"xen-devel@lists.xensource.com" <xen-devel@lists.xensource.com>
Subject: Re: lock in vhpet
Date: Wed, 18 Apr 2012 10:14:35 +0100	[thread overview]
Message-ID: <CBB4448D.3E643%keir@xen.org> (raw)
In-Reply-To: <CBB439E3.3E625%keir@xen.org>

[-- Attachment #1: Type: text/plain, Size: 896 bytes --]

On 18/04/2012 09:29, "Keir Fraser" <keir@xen.org> wrote:

> On 18/04/2012 08:55, "Zhang, Yang Z" <yang.z.zhang@intel.com> wrote:
> 
>>> If the HPET accesses are atomic on bare metal, we have to maintain that,
>>> even
>>> if some guests have extra locking themselves. Also, in some cases Xen needs
>>> locking to correctly maintain its own internal state regardless of what an
>>> (untrusted) guest might do. So we cannot just get rid of the vhpet lock
>>> everywhere. It's definitely not correct to do so. Optimising the hpet read
>>> path
>>> however, sounds okay. I agree the lock may not be needed on that specific
>>> path.
>> 
>> You are right.
>> For this case, since the main access of hpet is to read the main counter, so
>> I
>> think the rwlock is a better choice.
> 
> I'll see if I can make a patch...

Please try the attached patch (build tested only).

 -- Keir

>  -- Keir
> 
> 


[-- Attachment #2: 00-hpet-lockfree --]
[-- Type: application/octet-stream, Size: 5154 bytes --]

diff -r cf129a80e47e xen/arch/x86/hvm/hpet.c
--- a/xen/arch/x86/hvm/hpet.c	Tue Apr 17 15:37:05 2012 +0200
+++ b/xen/arch/x86/hvm/hpet.c	Wed Apr 18 10:13:07 2012 +0100
@@ -73,14 +73,36 @@
     ((timer_config(h, n) & HPET_TN_INT_ROUTE_CAP_MASK) \
         >> HPET_TN_INT_ROUTE_CAP_SHIFT)
 
-static inline uint64_t hpet_read_maincounter(HPETState *h)
+/*
+ * hpet_{read,set}_maincounter():
+ *  Atomically get/set h->mc_config to allow safe lock-free read access to
+ *  the HPET main counter. mc_config[0] is 1 when the counter is enabled.
+ *  When the counter is disabled, mc_config[63:1] is the counter value.
+ *  When the counter is enabled, mc_config[63:1] is a signed counter offset.
+ */
+static uint64_t hpet_read_maincounter(HPETState *h)
 {
+    int64_t mc_config = read_atomic(&h->mc_config);
+    int64_t counter = mc_config >> 1;
+    bool_t enabled = mc_config & 1;
+
+    if ( enabled )
+        counter += guest_time_hpet(h);
+
+    return (uint64_t)counter;
+}
+
+static void hpet_set_maincounter(HPETState *h)
+{
+    int64_t mc_config;
+
     ASSERT(spin_is_locked(&h->lock));
 
-    if ( hpet_enabled(h) )
-        return guest_time_hpet(h) + h->mc_offset;
-    else 
-        return h->hpet.mc64;
+    mc_config = (hpet_enabled(h)
+                 ? (((h->hpet.mc64 - guest_time_hpet(h)) << 1) | 1ull)
+                 : (h->hpet.mc64 << 1));
+
+    write_atomic(&h->mc_config, mc_config);
 }
 
 static uint64_t hpet_get_comparator(HPETState *h, unsigned int tn)
@@ -107,7 +129,8 @@ static uint64_t hpet_get_comparator(HPET
     h->hpet.timers[tn].cmp = comparator;
     return comparator;
 }
-static inline uint64_t hpet_read64(HPETState *h, unsigned long addr)
+
+static uint64_t __hpet_read64(HPETState *h, unsigned long addr)
 {
     addr &= ~7;
 
@@ -138,6 +161,23 @@ static inline uint64_t hpet_read64(HPETS
     return 0;
 }
 
+static uint64_t hpet_read64(HPETState *h, unsigned long addr)
+{
+    /* Allow lock-free access to main counter. */
+    bool_t lock = ((addr & ~7) != HPET_COUNTER);
+    uint64_t val;
+
+    if ( lock )
+        spin_lock(&h->lock);
+
+    val = __hpet_read64(h, addr);
+
+    if ( lock )
+        spin_unlock(&h->lock);
+
+    return val;
+}
+
 static inline int hpet_check_access_length(
     unsigned long addr, unsigned long len)
 {
@@ -172,16 +212,12 @@ static int hpet_read(
         goto out;
     }
 
-    spin_lock(&h->lock);
-
     val = hpet_read64(h, addr);
 
     result = val;
     if ( length != 8 )
         result = (val >> ((addr & 7) * 8)) & ((1ULL << (length * 8)) - 1);
 
-    spin_unlock(&h->lock);
-
  out:
     *pval = result;
     return X86EMUL_OKAY;
@@ -291,7 +327,7 @@ static int hpet_write(
 
     spin_lock(&h->lock);
 
-    old_val = hpet_read64(h, addr);
+    old_val = __hpet_read64(h, addr);
     new_val = val;
     if ( length != 8 )
         new_val = hpet_fixup_reg(
@@ -306,7 +342,7 @@ static int hpet_write(
         if ( !(old_val & HPET_CFG_ENABLE) && (new_val & HPET_CFG_ENABLE) )
         {
             /* Enable main counter and interrupt generation. */
-            h->mc_offset = h->hpet.mc64 - guest_time_hpet(h);
+            hpet_set_maincounter(h);
             for ( i = 0; i < HPET_TIMER_NUM; i++ )
             {
                 h->hpet.comparator64[i] =
@@ -320,7 +356,7 @@ static int hpet_write(
         else if ( (old_val & HPET_CFG_ENABLE) && !(new_val & HPET_CFG_ENABLE) )
         {
             /* Halt main counter and disable interrupt generation. */
-            h->hpet.mc64 = h->mc_offset + guest_time_hpet(h);
+            hpet_set_maincounter(h);
             for ( i = 0; i < HPET_TIMER_NUM; i++ )
                 if ( timer_enabled(h, i) )
                     set_stop_timer(i);
@@ -476,7 +512,7 @@ static int hpet_save(struct domain *d, h
     spin_lock(&hp->lock);
 
     /* Write the proper value into the main counter */
-    hp->hpet.mc64 = hp->mc_offset + guest_time_hpet(hp);
+    hp->hpet.mc64 = hpet_read_maincounter(hp);
 
     /* Save the HPET registers */
     rc = _hvm_init_entry(h, HVM_SAVE_CODE(HPET), 0, HVM_SAVE_LENGTH(HPET));
@@ -554,8 +590,7 @@ static int hpet_load(struct domain *d, h
     }
 #undef C
     
-    /* Recalculate the offset between the main counter and guest time */
-    hp->mc_offset = hp->hpet.mc64 - guest_time_hpet(hp);
+    hpet_set_maincounter(hp);
 
     /* restart all timers */
 
diff -r cf129a80e47e xen/include/asm-x86/hvm/vpt.h
--- a/xen/include/asm-x86/hvm/vpt.h	Tue Apr 17 15:37:05 2012 +0200
+++ b/xen/include/asm-x86/hvm/vpt.h	Wed Apr 18 10:13:07 2012 +0100
@@ -94,7 +94,13 @@ typedef struct HPETState {
     uint64_t stime_freq;
     uint64_t hpet_to_ns_scale; /* hpet ticks to ns (multiplied by 2^10) */
     uint64_t hpet_to_ns_limit; /* max hpet ticks convertable to ns      */
-    uint64_t mc_offset;
+    /*
+     * mc_config: Allows safe lock-free read access to the main counter
+     *  bit 0: set if timer is enabled
+     *  1-63: main counter value (if timer enabled)
+     *  1-63: main counter offset from system time (if timer disabled)
+     */
+    int64_t mc_config;
     struct periodic_time pt[HPET_TIMER_NUM];
     spinlock_t lock;
 } HPETState;

[-- Attachment #3: Type: text/plain, Size: 126 bytes --]

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel

  reply	other threads:[~2012-04-18  9:14 UTC|newest]

Thread overview: 45+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-04-17  3:26 lock in vhpet Zhang, Yang Z
2012-04-17  7:27 ` Keir Fraser
2012-04-18  0:52   ` Zhang, Yang Z
2012-04-18  7:13     ` Keir Fraser
2012-04-18  7:55       ` Zhang, Yang Z
2012-04-18  8:29         ` Keir Fraser
2012-04-18  9:14           ` Keir Fraser [this message]
2012-04-18  9:30             ` Keir Fraser
2012-04-19  5:19               ` Zhang, Yang Z
2012-04-19  8:27                 ` Tim Deegan
2012-04-19  8:47                   ` Keir Fraser
2012-04-23  7:36                     ` Zhang, Yang Z
2012-04-23  7:43                       ` Jan Beulich
2012-04-23  8:15                         ` Zhang, Yang Z
2012-04-23  8:22                           ` Keir Fraser
2012-04-23  9:14                       ` Tim Deegan
2012-04-23 15:26                         ` Andres Lagar-Cavilla
2012-04-24  9:15                           ` Tim Deegan
2012-04-24 13:28                             ` Andres Lagar-Cavilla
2012-04-23 17:18                         ` Andres Lagar-Cavilla
2012-04-24  8:58                           ` Zhang, Yang Z
2012-04-24  9:16                             ` Tim Deegan
2012-04-25  0:27                               ` Zhang, Yang Z
2012-04-25  1:40                                 ` Andres Lagar-Cavilla
2012-04-25  1:48                                   ` Zhang, Yang Z
2012-04-25  2:31                                     ` Andres Lagar-Cavilla
2012-04-25  2:36                                       ` Zhang, Yang Z
2012-04-25  2:42                                         ` Andres Lagar-Cavilla
2012-04-25  3:12                                           ` Zhang, Yang Z
2012-04-25  3:34                                             ` Andres Lagar-Cavilla
2012-04-25  5:18                                               ` Zhang, Yang Z
2012-04-25  8:07                                               ` Jan Beulich
2012-04-26 21:25                                         ` Tim Deegan
2012-04-27  0:46                                           ` Zhang, Yang Z
2012-04-27  0:51                                             ` Andres Lagar-Cavilla
2012-04-27  1:24                                               ` Zhang, Yang Z
2012-04-27  8:36                                               ` Zhang, Yang Z
2012-04-27  3:02                                           ` Andres Lagar-Cavilla
2012-04-27  9:26                                             ` Tim Deegan
2012-04-27 14:17                                               ` Andres Lagar-Cavilla
2012-04-27 21:08                                               ` Andres Lagar-Cavilla
2012-05-16 11:36                                           ` Zhang, Yang Z
2012-05-16 12:36                                             ` Tim Deegan
2012-05-17 10:57                                               ` Tim Deegan
2012-05-28  6:54                                                 ` Zhang, Yang Z

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=CBB4448D.3E643%keir@xen.org \
    --to=keir@xen.org \
    --cc=xen-devel@lists.xensource.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).