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] [xen-unstable] [XEN] Provide PV guests with emulated PIT

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] [XEN] Provide PV guests with emulated PIT.
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Thu, 14 Dec 2006 19:20:21 +0000
Delivery-date: Thu, 14 Dec 2006 11:20:27 -0800
Envelope-to: www-data@xxxxxxxxxxxxxxxxxx
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 kfraser@xxxxxxxxxxxxxxxxxxxxx
# Node ID cd89771ba5508e9d1d8c76448c11dc9809e1e70d
# Parent  afc6b5a60866d79d86af934515cf13f847acf6fc
[XEN] Provide PV guests with emulated PIT.
This is needed for some video-controller BIOSes which use PIT channel
2 for delay loops.
Signed-off-by: Xiaowei Yang <xiaowei.yang@xxxxxxxxx>
---
 xen/arch/x86/domain.c         |    4 ++++
 xen/arch/x86/hvm/hvm.c        |    1 -
 xen/arch/x86/hvm/i8254.c      |   41 ++++++++++++++++++++++++++++++++---------
 xen/arch/x86/traps.c          |   28 +++++++++++++++-------------
 xen/include/asm-x86/hvm/vpt.h |    2 +-
 5 files changed, 52 insertions(+), 24 deletions(-)

diff -r afc6b5a60866 -r cd89771ba550 xen/arch/x86/domain.c
--- a/xen/arch/x86/domain.c     Thu Dec 14 16:00:31 2006 +0000
+++ b/xen/arch/x86/domain.c     Thu Dec 14 16:27:10 2006 +0000
@@ -136,6 +136,10 @@ int vcpu_initialise(struct vcpu *v)
 
     pae_l3_cache_init(&v->arch.pae_l3_cache);
 
+    /* This should move to arch_domain_create(). */
+    if ( !is_idle_domain(d) && (v->vcpu_id == 0) )
+        pit_init(v, cpu_khz);
+
     if ( is_hvm_domain(d) )
     {
         if ( (rc = hvm_vcpu_initialise(v)) != 0 )
diff -r afc6b5a60866 -r cd89771ba550 xen/arch/x86/hvm/hvm.c
--- a/xen/arch/x86/hvm/hvm.c    Thu Dec 14 16:00:31 2006 +0000
+++ b/xen/arch/x86/hvm/hvm.c    Thu Dec 14 16:27:10 2006 +0000
@@ -222,7 +222,6 @@ int hvm_vcpu_initialise(struct vcpu *v)
 
     init_timer(&platform->pl_time.periodic_tm.timer,
                pt_timer_fn, v, v->processor);
-    pit_init(v, cpu_khz);
     rtc_init(v, RTC_PORT(0), RTC_IRQ);
     pmtimer_init(v, ACPI_PM_TMR_BLK_ADDRESS);
 
diff -r afc6b5a60866 -r cd89771ba550 xen/arch/x86/hvm/i8254.c
--- a/xen/arch/x86/hvm/i8254.c  Thu Dec 14 16:00:31 2006 +0000
+++ b/xen/arch/x86/hvm/i8254.c  Thu Dec 14 16:27:10 2006 +0000
@@ -184,12 +184,18 @@ void pit_time_fired(struct vcpu *v, void
 
 static inline void pit_load_count(PITChannelState *s, int val)
 {
-    u32   period;
+    u32 period;
+    PITChannelState *ch0 =
+        &current->domain->arch.hvm_domain.pl_time.vpit.channels[0];
+
     if (val == 0)
         val = 0x10000;
     s->count_load_time = hvm_get_clock(s->vcpu);
     s->count = val;
     period = DIV_ROUND((val * 1000000000ULL), PIT_FREQ);
+
+    if (s != ch0)
+        return;
 
 #ifdef DEBUG_PIT
     printk("HVM_PIT: pit-load-counter(%p), count=0x%x, period=%uns mode=%d, 
load_time=%lld\n",
@@ -419,13 +425,12 @@ static void speaker_ioport_write(void *o
 
 static uint32_t speaker_ioport_read(void *opaque, uint32_t addr)
 {
-    int out;
-    PITState *pit = opaque;
-    out = pit_get_out(pit, 2, hvm_get_clock(pit->channels[2].vcpu));
-    pit->dummy_refresh_clock ^= 1;
-
-    return (pit->speaker_data_on << 1) | pit_get_gate(pit, 2) | (out << 5) |
-      (pit->dummy_refresh_clock << 4);
+    PITState *pit = opaque;
+    int out = pit_get_out(pit, 2, hvm_get_clock(pit->channels[2].vcpu));
+    /* Refresh clock toggles at about 15us. We approximate as 2^14ns. */
+    unsigned int refresh_clock = ((unsigned int)NOW() >> 14) & 1;
+    return ((pit->speaker_data_on << 1) | pit_get_gate(pit, 2) |
+            (out << 5) | refresh_clock << 4);
 }
 
 static int handle_speaker_io(ioreq_t *p)
@@ -439,7 +444,7 @@ static int handle_speaker_io(ioreq_t *p)
         printk("HVM_SPEAKER:wrong SPEAKER IO!\n");
         return 1;
     }
-    
+
     if (p->dir == 0) {/* write */
         speaker_ioport_write(vpit, p->addr, p->data);
     } else if (p->dir == 1) {/* read */
@@ -448,3 +453,21 @@ static int handle_speaker_io(ioreq_t *p)
 
     return 1;
 }
+
+int pv_pit_handler(int port, int data, int write)
+{
+    ioreq_t ioreq = {
+        .size = 1,
+        .type = IOREQ_TYPE_PIO,
+        .addr = port,
+        .dir  = write ? 0 : 1,
+        .data = write ? data : 0,
+    };
+
+    if (port == 0x61)
+        handle_speaker_io(&ioreq);
+    else
+        handle_pit_io(&ioreq);
+
+    return !write ? ioreq.data : 0;
+}
diff -r afc6b5a60866 -r cd89771ba550 xen/arch/x86/traps.c
--- a/xen/arch/x86/traps.c      Thu Dec 14 16:00:31 2006 +0000
+++ b/xen/arch/x86/traps.c      Thu Dec 14 16:27:10 2006 +0000
@@ -59,6 +59,7 @@
 #include <asm/debugger.h>
 #include <asm/msr.h>
 #include <asm/x86_emulate.h>
+#include <asm/hvm/vpt.h>
 
 /*
  * opt_nmi: one of 'ignore', 'dom0', or 'fatal'.
@@ -1035,18 +1036,7 @@ static inline int admin_io_okay(
     return ioports_access_permitted(v->domain, port, port + bytes - 1);
 }
 
-static inline int guest_inb_okay(
-    unsigned int port, struct vcpu *v, struct cpu_user_regs *regs)
-{
-    /*
-     * Allow read access to port 0x61. Bit 4 oscillates with period 30us, and
-     * so it is often used for timing loops in BIOS code. This hack can go
-     * away when we have separate read/write permission rangesets.
-     * Note that we could emulate bit 4 instead of directly reading port 0x61,
-     * but there's not really a good reason to do so.
-     */
-    return (admin_io_okay(port, 1, v, regs) || (port == 0x61));
-}
+#define guest_inb_okay(_p, _d, _r) admin_io_okay(_p, 1, _d, _r)
 #define guest_inw_okay(_p, _d, _r) admin_io_okay(_p, 2, _d, _r)
 #define guest_inl_okay(_p, _d, _r) admin_io_okay(_p, 4, _d, _r)
 #define guest_outb_okay(_p, _d, _r) admin_io_okay(_p, 1, _d, _r)
@@ -1141,7 +1131,10 @@ static int emulate_privileged_op(struct 
             switch ( op_bytes )
             {
             case 1:
-                data = (u8)(guest_inb_okay(port, v, regs) ? inb(port) : ~0);
+                /* emulate PIT counter 2 */
+                data = (u8)(guest_inb_okay(port, v, regs) ? inb(port) : 
+                       ((port == 0x42 || port == 0x43 || port == 0x61) ?
+                       pv_pit_handler(port, 0, 0) : ~0)); 
                 break;
             case 2:
                 data = (u16)(guest_inw_okay(port, v, regs) ? inw(port) : ~0);
@@ -1176,6 +1169,8 @@ static int emulate_privileged_op(struct 
             case 1:
                 if ( guest_outb_okay(port, v, regs) )
                     outb((u8)data, port);
+                else if ( port == 0x42 || port == 0x43 || port == 0x61 )
+                    pv_pit_handler(port, data, 1);
                 break;
             case 2:
                 if ( guest_outw_okay(port, v, regs) )
@@ -1240,6 +1235,11 @@ static int emulate_privileged_op(struct 
         case 1:
             if ( guest_inb_okay(port, v, regs) )
                 io_emul(regs);
+            else if ( port == 0x42 || port == 0x43 || port == 0x61 )
+            {
+                regs->eax &= ~0xffUL;
+                regs->eax |= pv_pit_handler(port, 0, 0);
+            } 
             else
                 regs->eax |= (u8)~0;
             break;
@@ -1277,6 +1277,8 @@ static int emulate_privileged_op(struct 
         case 1:
             if ( guest_outb_okay(port, v, regs) )
                 io_emul(regs);
+            else if ( port == 0x42 || port == 0x43 || port == 0x61 )
+                pv_pit_handler(port, regs->eax, 1);
             break;
         case 2:
             if ( guest_outw_okay(port, v, regs) )
diff -r afc6b5a60866 -r cd89771ba550 xen/include/asm-x86/hvm/vpt.h
--- a/xen/include/asm-x86/hvm/vpt.h     Thu Dec 14 16:00:31 2006 +0000
+++ b/xen/include/asm-x86/hvm/vpt.h     Thu Dec 14 16:27:10 2006 +0000
@@ -54,7 +54,6 @@ typedef struct PITState {
 typedef struct PITState {
     PITChannelState channels[3];
     int speaker_data_on;
-    int dummy_refresh_clock;
 } PITState;
 
 #define RTC_SIZE 14
@@ -125,6 +124,7 @@ extern struct periodic_time *create_peri
 extern struct periodic_time *create_periodic_time(
     u32 period, char irq, char one_shot, time_cb *cb, void *data);
 extern void destroy_periodic_time(struct periodic_time *pt);
+int pv_pit_handler(int port, int data, int write);
 void pit_init(struct vcpu *v, unsigned long cpu_khz);
 void rtc_init(struct vcpu *v, int base, int irq);
 void rtc_deinit(struct domain *d);

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

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [xen-unstable] [XEN] Provide PV guests with emulated PIT., Xen patchbot-unstable <=