WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[Xen-changelog] Add HPET support to Xen. It is quicker to access and mor

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] Add HPET support to Xen. It is quicker to access and more
From: Xen patchbot -unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Wed, 27 Jul 2005 11:32:10 -0400
Delivery-date: Wed, 27 Jul 2005 15:32:35 +0000
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# HG changeset patch
# User kaf24@xxxxxxxxxxxxxxxxxxxx
# Node ID b7e975425dd677520c630f92e2a2d6d2668cb1d5
# Parent  7599a943b39e5eb2ed612d0738cf27913cb78885
Add HPET support to Xen. It is quicker to access and more
precise than the PIT.
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>

diff -r 7599a943b39e -r b7e975425dd6 xen/arch/x86/acpi/boot.c
--- a/xen/arch/x86/acpi/boot.c  Wed Jul 27 11:20:47 2005
+++ b/xen/arch/x86/acpi/boot.c  Wed Jul 27 15:32:44 2005
@@ -382,7 +382,7 @@
                return -1;
        }
 
-#ifdef CONFIG_X86_64
+#if 0/*def     CONFIG_X86_64*/
         vxtime.hpet_address = hpet_tbl->addr.addrl |
                 ((long) hpet_tbl->addr.addrh << 32);
 
diff -r 7599a943b39e -r b7e975425dd6 xen/arch/x86/time.c
--- a/xen/arch/x86/time.c       Wed Jul 27 11:20:47 2005
+++ b/xen/arch/x86/time.c       Wed Jul 27 15:32:44 2005
@@ -28,11 +28,18 @@
 #include <asm/fixmap.h>
 #include <asm/mc146818rtc.h>
 #include <asm/div64.h>
+#include <asm/hpet.h>
 #include <io_ports.h>
 
+/* opt_hpet_force: If true, force HPET configuration via PCI space. */
+/* NB. This is a gross hack. Mainly useful for HPET testing. */
+static int opt_hpet_force = 0;
+boolean_param("hpet_force", opt_hpet_force);
+
 #define EPOCH MILLISECS(1000)
 
 unsigned long cpu_khz;  /* CPU clock frequency in kHz. */
+unsigned long hpet_address;
 spinlock_t rtc_lock = SPIN_LOCK_UNLOCKED;
 int timer_ack = 0;
 unsigned long volatile jiffies;
@@ -58,6 +65,7 @@
 static u64 platform_timer_stamp;
 static struct time_scale platform_timer_scale;
 static spinlock_t platform_timer_lock = SPIN_LOCK_UNLOCKED;
+static u64 (*read_platform_count)(void);
 
 static inline u32 down_shift(u64 time, int shift)
 {
@@ -225,8 +233,13 @@
     atomic_dec(&tsc_calibrate_gang);
 }
 
+
+/************************************************************
+ * PLATFORM TIMER 1: PROGRAMMABLE INTERVAL TIMER (LEGACY PIT)
+ */
+
 /* Protected by platform_timer_lock. */
-static u64 platform_pit_counter;
+static u64 pit_counter64;
 static u16 pit_stamp;
 static struct ac_timer pit_overflow_timer;
 
@@ -246,20 +259,136 @@
 
     spin_lock(&platform_timer_lock);
     counter = pit_read_counter();
-    platform_pit_counter += (u16)(pit_stamp - counter);
+    pit_counter64 += (u16)(pit_stamp - counter);
     pit_stamp = counter;
     spin_unlock(&platform_timer_lock);
 
     set_ac_timer(&pit_overflow_timer, NOW() + MILLISECS(20));
 }
 
-static void init_platform_timer(void)
-{
+static u64 read_pit_count(void)
+{
+    return pit_counter64 + (u16)(pit_stamp - pit_read_counter());
+}
+
+static int init_pit(void)
+{
+    read_platform_count = read_pit_count;
+
     init_ac_timer(&pit_overflow_timer, pit_overflow, NULL, 0);
     pit_overflow(NULL);
-    platform_timer_stamp = platform_pit_counter;
+    platform_timer_stamp = pit_counter64;
     set_time_scale(&platform_timer_scale, CLOCK_TICK_RATE);
-}
+
+    return 1;
+}
+
+/************************************************************
+ * PLATFORM TIMER 2: HIGH PRECISION EVENT TIMER (HPET)
+ */
+
+/* Protected by platform_timer_lock. */
+static u64 hpet_counter64, hpet_overflow_period;
+static u32 hpet_stamp;
+static struct ac_timer hpet_overflow_timer;
+
+static void hpet_overflow(void *unused)
+{
+    u32 counter;
+
+    spin_lock(&platform_timer_lock);
+    counter = hpet_read32(HPET_COUNTER);
+    hpet_counter64 += (u32)(counter - hpet_stamp);
+    hpet_stamp = counter;
+    spin_unlock(&platform_timer_lock);
+
+    set_ac_timer(&hpet_overflow_timer, NOW() + hpet_overflow_period);
+}
+
+static u64 read_hpet_count(void)
+{
+    return hpet_counter64 + (u32)(hpet_read32(HPET_COUNTER) - hpet_stamp);
+}
+
+static int init_hpet(void)
+{
+    u64 hpet_rate;
+    u32 hpet_id, hpet_period, cfg;
+    int i;
+
+    if ( (hpet_address == 0) && opt_hpet_force )
+    {
+               printk(KERN_WARNING "WARNING: Enabling HPET base manually!\n");
+        outl(0x800038a0, 0xcf8);
+        outl(0xff000001, 0xcfc);
+        outl(0x800038a0, 0xcf8);
+        hpet_address = inl(0xcfc) & 0xfffffffe;
+               printk(KERN_WARNING "WARNING: Enabled HPET at %#lx.\n", 
hpet_address);
+    }
+
+    if ( hpet_address == 0 )
+        return 0;
+
+    set_fixmap_nocache(FIX_HPET_BASE, hpet_address);
+
+    hpet_id = hpet_read32(HPET_ID);
+    if ( hpet_id == 0 )
+    {
+        printk("BAD HPET vendor id.\n");
+        return 0;
+    }
+
+    /* Check for sane period (100ps <= period <= 100ns). */
+    hpet_period = hpet_read32(HPET_PERIOD);
+    if ( (hpet_period > 100000000) || (hpet_period < 100000) )
+    {
+        printk("BAD HPET period %u.\n", hpet_period);
+        return 0;
+    }
+
+    cfg = hpet_read32(HPET_CFG);
+    cfg &= ~(HPET_CFG_ENABLE | HPET_CFG_LEGACY);
+    hpet_write32(cfg, HPET_CFG);
+
+    for ( i = 0; i <= ((hpet_id >> 8) & 31); i++ )
+    {
+        cfg = hpet_read32(HPET_T0_CFG + i*0x20);
+        cfg &= ~HPET_TN_ENABLE;
+        hpet_write32(cfg & ~HPET_TN_ENABLE, HPET_T0_CFG);
+    }
+
+    cfg = hpet_read32(HPET_CFG);
+    cfg |= HPET_CFG_ENABLE;
+    hpet_write32(cfg, HPET_CFG);
+
+    read_platform_count = read_hpet_count;
+
+    hpet_rate = 1000000000000000ULL; /* 10^15 */
+    (void)do_div(hpet_rate, hpet_period);
+    set_time_scale(&platform_timer_scale, hpet_rate);
+
+    /* Trigger overflow avoidance roughly when counter increments 2^31. */
+    if ( (hpet_rate >> 31) != 0 )
+    {
+        hpet_overflow_period = MILLISECS(1000);
+        (void)do_div(hpet_overflow_period, (u32)(hpet_rate >> 31) + 1);
+    }
+    else
+    {
+        hpet_overflow_period = MILLISECS(1000) << 31;
+        (void)do_div(hpet_overflow_period, (u32)hpet_rate);
+    }
+
+    init_ac_timer(&hpet_overflow_timer, hpet_overflow, NULL, 0);
+    hpet_overflow(NULL);
+    platform_timer_stamp = hpet_counter64;
+
+    return 1;
+}
+
+/************************************************************
+ * GENERIC PLATFORM TIMER INFRASTRUCTURE
+ */
 
 static s_time_t __read_platform_stime(u64 platform_time)
 {
@@ -276,7 +405,7 @@
     s_time_t stime;
 
     spin_lock(&platform_timer_lock);
-    counter = platform_pit_counter + (u16)(pit_stamp - pit_read_counter());
+    counter = read_platform_count();
     stime   = __read_platform_stime(counter);
     spin_unlock(&platform_timer_lock);
 
@@ -289,11 +418,17 @@
     s_time_t stamp;
 
     spin_lock(&platform_timer_lock);
-    counter = platform_pit_counter + (u16)(pit_stamp - pit_read_counter());
+    counter = read_platform_count();
     stamp   = __read_platform_stime(counter);
     stime_platform_stamp = stamp;
     platform_timer_stamp = counter;
     spin_unlock(&platform_timer_lock);
+}
+
+static void init_platform_timer(void)
+{
+    if ( !init_hpet() )
+        BUG_ON(!init_pit());
 }
 
 
@@ -494,9 +629,8 @@
 #if 0
     printk("PRE%d: tsc=%lld stime=%lld master=%lld\n",
            cpu, prev_tsc, prev_local_stime, prev_master_stime);
-    printk("CUR%d: tsc=%lld stime=%lld master=%lld %lld\n",
-           cpu, curr_tsc, curr_local_stime, curr_master_stime,
-           platform_pit_counter);
+    printk("CUR%d: tsc=%lld stime=%lld master=%lld\n",
+           cpu, curr_tsc, curr_local_stime, curr_master_stime);
 #endif
 
     /* Local time warps forward if it lags behind master time. */
diff -r 7599a943b39e -r b7e975425dd6 xen/include/asm-x86/config.h
--- a/xen/include/asm-x86/config.h      Wed Jul 27 11:20:47 2005
+++ b/xen/include/asm-x86/config.h      Wed Jul 27 15:32:44 2005
@@ -23,6 +23,7 @@
 #define CONFIG_X86_LOCAL_APIC 1
 #define CONFIG_X86_GOOD_APIC 1
 #define CONFIG_X86_IO_APIC 1
+#define CONFIG_HPET_TIMER 1
 
 /* Intel P4 currently has largest cache line (L2 line size is 128 bytes). */
 #define CONFIG_X86_L1_CACHE_SHIFT 7
diff -r 7599a943b39e -r b7e975425dd6 xen/include/asm-x86/fixmap.h
--- a/xen/include/asm-x86/fixmap.h      Wed Jul 27 11:20:47 2005
+++ b/xen/include/asm-x86/fixmap.h      Wed Jul 27 15:32:44 2005
@@ -30,6 +30,7 @@
     FIX_IO_APIC_BASE_END = FIX_IO_APIC_BASE_0 + MAX_IO_APICS-1,
     FIX_ACPI_BEGIN,
     FIX_ACPI_END = FIX_ACPI_BEGIN + FIX_ACPI_PAGES - 1,
+    FIX_HPET_BASE,
     __end_of_fixed_addresses
 };
 
diff -r 7599a943b39e -r b7e975425dd6 xen/include/asm-x86/hpet.h
--- /dev/null   Wed Jul 27 11:20:47 2005
+++ b/xen/include/asm-x86/hpet.h        Wed Jul 27 15:32:44 2005
@@ -0,0 +1,52 @@
+#ifndef __X86_HPET_H__
+#define __X86_HPET_H__
+
+/*
+ * Documentation on HPET can be found at:
+ *      http://www.intel.com/ial/home/sp/pcmmspec.htm
+ *      ftp://download.intel.com/ial/home/sp/mmts098.pdf
+ */
+
+#define HPET_MMAP_SIZE 1024
+
+#define HPET_ID                0x000
+#define HPET_PERIOD    0x004
+#define HPET_CFG       0x010
+#define HPET_STATUS    0x020
+#define HPET_COUNTER   0x0f0
+#define HPET_T0_CFG    0x100
+#define HPET_T0_CMP    0x108
+#define HPET_T0_ROUTE  0x110
+#define HPET_T1_CFG    0x120
+#define HPET_T1_CMP    0x128
+#define HPET_T1_ROUTE  0x130
+#define HPET_T2_CFG    0x140
+#define HPET_T2_CMP    0x148
+#define HPET_T2_ROUTE  0x150
+
+#define HPET_ID_VENDOR 0xffff0000
+#define HPET_ID_LEGSUP 0x00008000
+#define HPET_ID_NUMBER 0x00001f00
+#define HPET_ID_REV    0x000000ff
+#define        HPET_ID_NUMBER_SHIFT    8
+
+#define HPET_ID_VENDOR_SHIFT   16
+#define HPET_ID_VENDOR_8086    0x8086
+
+#define HPET_CFG_ENABLE        0x001
+#define HPET_CFG_LEGACY        0x002
+#define        HPET_LEGACY_8254        2
+#define        HPET_LEGACY_RTC         8
+
+#define HPET_TN_ENABLE         0x004
+#define HPET_TN_PERIODIC       0x008
+#define HPET_TN_PERIODIC_CAP   0x010
+#define HPET_TN_SETVAL         0x040
+#define HPET_TN_32BIT          0x100
+
+#define hpet_read32(x)    \
+    (*(volatile u32 *)(fix_to_virt(FIX_HPET_BASE) + (x)))
+#define hpet_write32(y,x) \
+    (*(volatile u32 *)(fix_to_virt(FIX_HPET_BASE) + (x)) = (y))
+
+#endif /* __X86_HPET_H__ */

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] Add HPET support to Xen. It is quicker to access and more, Xen patchbot -unstable <=