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] merge

# HG changeset patch
# User awilliam@xxxxxxxxxxx
# Node ID 25003dd43a92eb8c4ef6d87475e903615337225a
# Parent  e04978011d2d7197e0a4b4057454d40a200f0e0a
# Parent  3377e445aa5e949cd62f7993a0dd62d2aebde4d1
merge

diff -r e04978011d2d -r 25003dd43a92 docs/src/interface.tex
--- a/docs/src/interface.tex    Fri Mar 17 21:26:24 2006
+++ b/docs/src/interface.tex    Fri Mar 17 22:37:28 2006
@@ -128,7 +128,7 @@
 \section{Exceptions}
 
 A virtual IDT is provided --- a domain can submit a table of trap
-handlers to Xen via the {\tt set\_trap\_table()} hypercall.  The
+handlers to Xen via the {\bf set\_trap\_table} hypercall.  The
 exception stack frame presented to a virtual trap handler is identical
 to its native equivalent.
 
@@ -137,7 +137,7 @@
 
 Interrupts are virtualized by mapping them to \emph{event channels},
 which are delivered asynchronously to the target domain using a callback
-supplied via the {\tt set\_callbacks()} hypercall.  A guest OS can map
+supplied via the {\bf set\_callbacks} hypercall.  A guest OS can map
 these events onto its standard interrupt dispatch mechanisms.  Xen is
 responsible for determining the target domain that will handle each
 physical interrupt source. For more details on the binding of event
@@ -167,7 +167,7 @@
 
 \item[Wall clock time.]
 
-  This is the time of day in a Unix-style {\tt struct timeval}
+  This is the time of day in a Unix-style {\bf struct timeval}
   (seconds and microseconds since 1 January 1970, adjusted by leap
   seconds).  An NTP client hosted by {\it domain 0} can keep this
   value accurate.
@@ -200,8 +200,8 @@
 timer event whenever a domain is scheduled; this allows the guest OS
 to adjust for the time that has passed while it has been inactive.  In
 addition, Xen allows each domain to request that they receive a timer
-event sent at a specified system time by using the {\tt
-  set\_timer\_op()} hypercall.  Guest OSes may use this timer to
+event sent at a specified system time by using the {\bf
+  set\_timer\_op} hypercall.  Guest OSes may use this timer to
 implement timeout values when they block.
 
 
@@ -232,7 +232,7 @@
 
 
 %% More information on the characteristics and use of these schedulers
-%% is available in {\tt Sched-HOWTO.txt}.
+%% is available in {\bf Sched-HOWTO.txt}.
 
 
 \section{Privileged operations}
@@ -354,7 +354,7 @@
 uses Xen's explicit page-table update interfaces.
 
 Writable pagetable functionality is enabled when the guest requests
-it, using a {\tt vm\_assist} hypercall.  Writable pagetables do {\em
+it, using a {\bf vm\_assist} hypercall.  Writable pagetables do {\em
 not} provide full virtualisation of the MMU, so the memory management
 code of the guest still needs to be aware that it is running on Xen.
 Since the guest's page tables are used directly, it must translate
@@ -400,7 +400,7 @@
 \end{quote}
 
 The LDT is updated via the generic MMU update mechanism (i.e., via the
-{\tt mmu\_update()} hypercall.
+{\bf mmu\_update} hypercall.
 
 \section{Start of Day}
 
@@ -423,8 +423,8 @@
 
 \hypercall{vm\_assist(unsigned int cmd, unsigned int type)}
 
-The {\tt cmd} parameter describes the action to be taken, whilst the
-{\tt type} parameter describes the kind of assist that is being
+The {\bf cmd} parameter describes the action to be taken, whilst the
+{\bf type} parameter describes the kind of assist that is being
 referred to.  Available commands are as follows:
 
 \begin{description}
@@ -453,18 +453,18 @@
 status, time information and event channel (virtual interrupt) state.
 The {\bf Start info page} is used to pass build-time information to
 the guest when it boots and when it is resumed from a suspended state.
-This chapter documents the fields included in the {\tt
-shared\_info\_t} and {\tt start\_info\_t} structures for use by the
+This chapter documents the fields included in the {\bf
+shared\_info\_t} and {\bf start\_info\_t} structures for use by the
 guest OS.
 
 \section{Shared info page}
 
-The {\tt shared\_info\_t} is accessed at run time by both Xen and the
+The {\bf shared\_info\_t} is accessed at run time by both Xen and the
 guest OS.  It is used to pass information relating to the
 virtual CPU and virtual machine state between the OS and the
 hypervisor.
 
-The structure is declared in {\tt xen/include/public/xen.h}:
+The structure is declared in {\bf xen/include/public/xen.h}:
 
 \scriptsize
 \begin{verbatim}
@@ -520,7 +520,7 @@
 \normalsize
 
 \begin{description}
-\item[vcpu\_info] An array of {\tt vcpu\_info\_t} structures, each of
+\item[vcpu\_info] An array of {\bf vcpu\_info\_t} structures, each of
   which holds either runtime information about a virtual CPU, or is
   ``empty'' if the corresponding VCPU does not exist.
 \item[evtchn\_pending] Guest-global array, with one bit per event
@@ -579,11 +579,11 @@
   that there are pending events to be received.
 \item[evtchn\_upcall\_mask] This is set non-zero to disable all
   interrupts for this CPU for short periods of time.  If individual
-  event channels need to be masked, the {\tt evtchn\_mask} in the {\tt
+  event channels need to be masked, the {\bf evtchn\_mask} in the {\bf
   shared\_info\_t} is used instead.
 \item[evtchn\_pending\_sel] When an event is delivered to this VCPU, a
-  bit is set in this selector to indicate which word of the {\tt
-  evtchn\_pending} array in the {\tt shared\_info\_t} contains the
+  bit is set in this selector to indicate which word of the {\bf
+  evtchn\_pending} array in the {\bf shared\_info\_t} contains the
   event in question.
 \item[arch] Architecture-specific VCPU info. On x86 this contains the
   virtualized CR2 register (page fault linear address) for this VCPU.
@@ -634,7 +634,7 @@
 
 \subsection{arch\_shared\_info\_t}
 
-On x86, the {\tt arch\_shared\_info\_t} is defined as follows (from
+On x86, the {\bf arch\_shared\_info\_t} is defined as follows (from
 xen/public/arch-x86\_32.h):
 
 \scriptsize
@@ -656,7 +656,7 @@
 
 \section{Start info page}
 
-The start info structure is declared as the following (in {\tt
+The start info structure is declared as the following (in {\bf
 xen/include/public/xen.h}):
 
 \scriptsize
@@ -745,7 +745,7 @@
 
 The event channel operation hypercall is used for all operations on
 event channels / ports.  Operations are distinguished by the value of
-the {\tt cmd} field of the {\tt op} structure.  The possible commands
+the {\bf cmd} field of the {\bf op} structure.  The possible commands
 are described below:
 
 \begin{description}
@@ -880,12 +880,12 @@
 
 \hypercall{grant\_table\_op(unsigned int cmd, void *uop, unsigned int count)}
 
-{\tt cmd} indicates the grant table operation of interest.  {\tt uop}
+{\bf cmd} indicates the grant table operation of interest.  {\bf uop}
 is a pointer to a structure (or an array of structures) describing the
-operation to be performed.  The {\tt count} field describes how many
+operation to be performed.  The {\bf count} field describes how many
 grant table operations are being batched together.
 
-The core logic is situated in {\tt xen/common/grant\_table.c}.  The
+The core logic is situated in {\bf xen/common/grant\_table.c}.  The
 grant table operation hypercall can be used to perform the following
 actions:
 
@@ -957,9 +957,9 @@
 \item[/tool] stores information for the various tools
 \end{description}
 
-The {\tt /vm} path stores configuration information for a domain.
+The {\bf /vm} path stores configuration information for a domain.
 This information doesn't change and is indexed by the domain's UUID.
-A {\tt /vm} entry contains the following information:
+A {\bf /vm} entry contains the following information:
 
 \begin{description}
 \item[ssidref] ssid reference for domain
@@ -974,7 +974,7 @@
 \end{description}
 
 
-{\tt /vm/$<$uuid$>$/image/}
+{\bf /vm/$<$uuid$>$/image/}
 
 The image path is only available for Domain-Us and contains:
 \begin{description}
@@ -984,7 +984,7 @@
 \item[ramdisk] path to ramdisk on domain-0
 \end{description}
 
-{\tt /local}
+{\bf /local}
 
 The {\tt /local} path currently only contains one directory, {\tt
 /local/domain} that is indexed by domain id.  It contains the running
@@ -993,7 +993,7 @@
 {\tt /local/domain} directory can be created and populated before
 finalizing the migration enabling localhost to localhost migration.
 
-{\tt /local/domain/$<$domid$>$}
+{\bf /local/domain/$<$domid$>$}
 
 This path contains:
 
@@ -1663,10 +1663,10 @@
 event processing. In each case the code segment selector and 
 address within that segment are provided. The selectors must
 have RPL 1; in XenLinux we simply use the kernel's CS for both 
-{\tt event\_selector} and {\tt failsafe\_selector}.
-
-The value {\tt event\_address} specifies the address of the guest OSes
-event handling and dispatch routine; the {\tt failsafe\_address}
+{\bf event\_selector} and {\bf failsafe\_selector}.
+
+The value {\bf event\_address} specifies the address of the guest OSes
+event handling and dispatch routine; the {\bf failsafe\_address}
 specifies a separate entry point which is used only if a fault occurs
 when Xen attempts to use the normal callback. 
 
@@ -1692,7 +1692,7 @@
 
 Install one or more entries into the per-domain 
 trap handler table (essentially a software version of the IDT). 
-Each entry in the array pointed to by {\tt table} includes the 
+Each entry in the array pointed to by {\bf table} includes the 
 exception vector number with the corresponding segment selector 
 and entry point. Most guest OSes can use the same handlers on 
 Xen as when running on the real hardware.
@@ -1718,17 +1718,44 @@
 control certain behavior with the following hypercall: 
 
 \begin{quote} 
-\hypercall{sched\_op(unsigned long op)} 
-
-Request scheduling operation from hypervisor. The options are: {\it
-SCHEDOP\_yield}, {\it SCHEDOP\_block}, and {\it SCHEDOP\_shutdown}.
-{\it yield} keeps the calling domain runnable but may cause a
-reschedule if other domains are runnable.  {\it block} removes the
-calling domain from the run queue and cause is to sleeps until an
-event is delivered to it.  {\it shutdown} is used to end the domain's
-execution; the caller can additionally specify whether the domain
-should reboot, halt or suspend.
+\hypercall{sched\_op\_new(int cmd, void *extra\_args)}
+
+Request scheduling operation from hypervisor. The following
+sub-commands are available:
+
+\begin{description}
+\item[SCHEDOP\_yield] voluntarily yields the CPU, but leaves the
+caller marked as runnable. No extra arguments are passed to this
+command. 
+\item[SCHEDOP\_block] removes the calling domain from the run queue
+and causes it to sleep until an event is delivered to it. No extra 
+arguments are passed to this command. 
+\item[SCHEDOP\_shutdown] is used to end the calling domain's
+execution. The extra argument is a {\bf sched\_shutdown} structure
+which indicates the reason why the domain suspended (e.g., for reboot,
+halt, power-off).
+\item[SCHEDOP\_poll] allows a VCPU to wait on a set of event channels
+with an optional timeout (all of which are specified in the {\bf
+sched\_poll} extra argument). The semantics are similar to the UNIX
+{\bf poll} system call. The caller must have event-channel upcalls
+masked when executing this command.
+\end{description}
 \end{quote} 
+
+{\bf sched\_op\_new}  was not available prior to Xen 3.0.2. Older versions
+provide only the following hypercall:
+
+\begin{quote} 
+\hypercall{sched\_op(int cmd, unsigned long extra\_arg)}
+
+This hypercall supports the following subset of {\bf sched\_op\_new} commands:
+
+\begin{description}
+\item[SCHEDOP\_yield] (extra argument is 0).
+\item[SCHEDOP\_block] (extra argument is 0).
+\item[SCHEDOP\_shutdown] (extra argument is numeric reason code).
+\end{description}
+\end{quote}
 
 To aid the implementation of a process scheduler within a guest OS,
 Xen provides a virtual programmable timer:
@@ -1737,12 +1764,11 @@
 \hypercall{set\_timer\_op(uint64\_t timeout)} 
 
 Request a timer event to be sent at the specified system time (time 
-in nanoseconds since system boot). The hypercall actually passes the 
-64-bit timeout value as a pair of 32-bit values. 
+in nanoseconds since system boot).
 
 \end{quote} 
 
-Note that calling {\tt set\_timer\_op()} prior to {\tt sched\_op} 
+Note that calling {\bf set\_timer\_op} prior to {\bf sched\_op} 
 allows block-with-timeout semantics. 
 
 
@@ -1757,20 +1783,20 @@
 \begin{quote} 
 \hypercall{mmu\_update(mmu\_update\_t *req, int count, int *success\_count)} 
 
-Update the page table for the domain; a set of {\tt count} updates are
-submitted for processing in a batch, with {\tt success\_count} being 
+Update the page table for the domain; a set of {\bf count} updates are
+submitted for processing in a batch, with {\bf success\_count} being 
 updated to report the number of successful updates.  
 
-Each element of {\tt req[]} contains a pointer (address) and value; 
+Each element of {\bf req[]} contains a pointer (address) and value; 
 the least significant 2-bits of the pointer are used to distinguish 
 the type of update requested as follows:
 \begin{description} 
 
-\item[\it MMU\_NORMAL\_PT\_UPDATE:] update a page directory entry or
+\item[MMU\_NORMAL\_PT\_UPDATE:] update a page directory entry or
 page table entry to the associated value; Xen will check that the
 update is safe, as described in Chapter~\ref{c:memory}.
 
-\item[\it MMU\_MACHPHYS\_UPDATE:] update an entry in the
+\item[MMU\_MACHPHYS\_UPDATE:] update an entry in the
   machine-to-physical table. The calling domain must own the machine
   page in question (or be privileged).
 \end{description}
@@ -1792,9 +1818,9 @@
 \hypercall{update\_va\_mapping(unsigned long va, uint64\_t val,
                          unsigned long flags)}
 
-Update the currently installed PTE that maps virtual address {\tt va}
-to new value {\tt val}. As with {\tt mmu\_update()}, Xen checks the
-modification  is safe before applying it. The {\tt flags} determine
+Update the currently installed PTE that maps virtual address {\bf va}
+to new value {\bf val}. As with {\bf mmu\_update}, Xen checks the
+modification  is safe before applying it. The {\bf flags} determine
 which kind of TLB flush, if any, should follow the update. 
 
 \end{quote} 
@@ -1806,8 +1832,8 @@
 \hypercall{update\_va\_mapping(unsigned long va, uint64\_t val,
                          unsigned long flags, domid\_t domid)}
 
-Identical to {\tt update\_va\_mapping()} save that the pages being
-mapped must belong to the domain {\tt domid}. 
+Identical to {\bf update\_va\_mapping} save that the pages being
+mapped must belong to the domain {\bf domid}. 
 
 \end{quote}
 
@@ -1854,17 +1880,17 @@
 \begin{quote}
 \hypercall{set\_gdt(unsigned long *frame\_list, int entries)} 
 
-Install a global descriptor table for a domain; {\tt frame\_list} is
+Install a global descriptor table for a domain; {\bf frame\_list} is
 an array of up to 16 machine page frames within which the GDT resides,
-with {\tt entries} being the actual number of descriptor-entry
+with {\bf entries} being the actual number of descriptor-entry
 slots. All page frames must be mapped read-only within the guest's
 address space, and the table must be large enough to contain Xen's
-reserved entries (see {\tt xen/include/public/arch-x86\_32.h}).
+reserved entries (see {\bf xen/include/public/arch-x86\_32.h}).
 
 \end{quote}
 
 Many guest OSes will also wish to install LDTs; this is achieved by
-using {\tt mmu\_update()} with an extended command, passing the
+using {\bf mmu\_update} with an extended command, passing the
 linear address of the LDT base along with the number of entries. No
 special safety checks are required; Xen needs to perform this task
 simply since {\tt lldt} requires CPL 0.
@@ -1876,8 +1902,8 @@
 \begin{quote}
 \hypercall{update\_descriptor(uint64\_t ma, uint64\_t desc)}
 
-Update the GDT/LDT entry at machine address {\tt ma}; the new
-8-byte descriptor is stored in {\tt desc}.
+Update the GDT/LDT entry at machine address {\bf ma}; the new
+8-byte descriptor is stored in {\bf desc}.
 Xen performs a number of checks to ensure the descriptor is 
 valid. 
 
@@ -1897,8 +1923,8 @@
 \begin{quote} 
 \hypercall{stack\_switch(unsigned long ss, unsigned long esp)} 
 
-Request kernel stack switch from hypervisor; {\tt ss} is the new 
-stack segment, which {\tt esp} is the new stack pointer. 
+Request kernel stack switch from hypervisor; {\bf ss} is the new 
+stack segment, which {\bf esp} is the new stack pointer. 
 
 \end{quote} 
 
@@ -1939,18 +1965,18 @@
 \hypercall{memory\_op(unsigned int op, void *arg)}
 
 Increase or decrease current memory allocation (as determined by 
-the value of {\tt op}).  The available operations are:
+the value of {\bf op}).  The available operations are:
 
 \begin{description}
 \item[XENMEM\_increase\_reservation] Request an increase in machine
-  memory allocation; {\tt arg} must point to a {\tt
+  memory allocation; {\bf arg} must point to a {\bf
   xen\_memory\_reservation} structure.
 \item[XENMEM\_decrease\_reservation] Request a decrease in machine
-  memory allocation; {\tt arg} must point to a {\tt
+  memory allocation; {\bf arg} must point to a {\bf
   xen\_memory\_reservation} structure.
 \item[XENMEM\_maximum\_ram\_page] Request the frame number of the
-  highest-addressed frame of machine memory in the system.  {\tt arg}
-  must point to an {\tt unsigned long} where this value will be
+  highest-addressed frame of machine memory in the system.  {\bf arg}
+  must point to an {\bf unsigned long} where this value will be
   stored.
 \item[XENMEM\_current\_reservation] Returns current memory reservation
   of the specified domain.
@@ -1982,31 +2008,31 @@
 \begin{quote}
 \hypercall{event\_channel\_op(evtchn\_op\_t *op)} 
 
-Inter-domain event-channel management; {\tt op} is a discriminated 
+Inter-domain event-channel management; {\bf op} is a discriminated 
 union which allows the following 7 operations: 
 
 \begin{description} 
 
-\item[\it alloc\_unbound:] allocate a free (unbound) local
+\item[alloc\_unbound:] allocate a free (unbound) local
   port and prepare for connection from a specified domain. 
-\item[\it bind\_virq:] bind a local port to a virtual 
+\item[bind\_virq:] bind a local port to a virtual 
 IRQ; any particular VIRQ can be bound to at most one port per domain. 
-\item[\it bind\_pirq:] bind a local port to a physical IRQ;
+\item[bind\_pirq:] bind a local port to a physical IRQ;
 once more, a given pIRQ can be bound to at most one port per
 domain. Furthermore the calling domain must be sufficiently
 privileged.
-\item[\it bind\_interdomain:] construct an interdomain event 
+\item[bind\_interdomain:] construct an interdomain event 
 channel; in general, the target domain must have previously allocated 
 an unbound port for this channel, although this can be bypassed by 
 privileged domains during domain setup. 
-\item[\it close:] close an interdomain event channel. 
-\item[\it send:] send an event to the remote end of a 
+\item[close:] close an interdomain event channel. 
+\item[send:] send an event to the remote end of a 
 interdomain event channel. 
-\item[\it status:] determine the current status of a local port. 
+\item[status:] determine the current status of a local port. 
 \end{description} 
 
 For more details see
-{\tt xen/include/public/event\_channel.h}. 
+{\bf xen/include/public/event\_channel.h}. 
 
 \end{quote} 
 
@@ -2018,7 +2044,7 @@
 
 Safe sharing of memory pages between guest OSes is carried out by
 granting access on a per page basis to individual domains. This is
-achieved by using the {\tt grant\_table\_op()} hypercall.
+achieved by using the {\tt grant\_table\_op} hypercall.
 
 \begin{quote}
 \hypercall{grant\_table\_op(unsigned int cmd, void *uop, unsigned int count)}
@@ -2047,7 +2073,7 @@
 \end{quote} 
 
 
-For examples of using {\tt physdev\_op()}, see the 
+For examples of using {\tt physdev\_op}, see the 
 Xen-specific PCI code in the linux sparse tree. 
 
 \section{Administrative Operations}
@@ -2066,81 +2092,81 @@
 Administrative domain operations for domain management. The options are:
 
 \begin{description} 
-\item [\it DOM0\_GETMEMLIST:] get list of pages used by the domain
-
-\item [\it DOM0\_SCHEDCTL:]
-
-\item [\it DOM0\_ADJUSTDOM:] adjust scheduling priorities for domain
-
-\item [\it DOM0\_CREATEDOMAIN:] create a new domain
-
-\item [\it DOM0\_DESTROYDOMAIN:] deallocate all resources associated
+\item [DOM0\_GETMEMLIST:] get list of pages used by the domain
+
+\item [DOM0\_SCHEDCTL:]
+
+\item [DOM0\_ADJUSTDOM:] adjust scheduling priorities for domain
+
+\item [DOM0\_CREATEDOMAIN:] create a new domain
+
+\item [DOM0\_DESTROYDOMAIN:] deallocate all resources associated
 with a domain
 
-\item [\it DOM0\_PAUSEDOMAIN:] remove a domain from the scheduler run 
+\item [DOM0\_PAUSEDOMAIN:] remove a domain from the scheduler run 
 queue. 
 
-\item [\it DOM0\_UNPAUSEDOMAIN:] mark a paused domain as schedulable
+\item [DOM0\_UNPAUSEDOMAIN:] mark a paused domain as schedulable
   once again. 
 
-\item [\it DOM0\_GETDOMAININFO:] get statistics about the domain
-
-\item [\it DOM0\_SETDOMAININFO:] set VCPU-related attributes
-
-\item [\it DOM0\_MSR:] read or write model specific registers
-
-\item [\it DOM0\_DEBUG:] interactively invoke the debugger
-
-\item [\it DOM0\_SETTIME:] set system time
-
-\item [\it DOM0\_GETPAGEFRAMEINFO:] 
-
-\item [\it DOM0\_READCONSOLE:] read console content from hypervisor buffer ring
-
-\item [\it DOM0\_PINCPUDOMAIN:] pin domain to a particular CPU
-
-\item [\it DOM0\_TBUFCONTROL:] get and set trace buffer attributes
-
-\item [\it DOM0\_PHYSINFO:] get information about the host machine
-
-\item [\it DOM0\_SCHED\_ID:] get the ID of the current Xen scheduler
-
-\item [\it DOM0\_SHADOW\_CONTROL:] switch between shadow page-table modes
-
-\item [\it DOM0\_SETDOMAINMAXMEM:] set maximum memory allocation of a domain
-
-\item [\it DOM0\_GETPAGEFRAMEINFO2:] batched interface for getting
+\item [DOM0\_GETDOMAININFO:] get statistics about the domain
+
+\item [DOM0\_SETDOMAININFO:] set VCPU-related attributes
+
+\item [DOM0\_MSR:] read or write model specific registers
+
+\item [DOM0\_DEBUG:] interactively invoke the debugger
+
+\item [DOM0\_SETTIME:] set system time
+
+\item [DOM0\_GETPAGEFRAMEINFO:] 
+
+\item [DOM0\_READCONSOLE:] read console content from hypervisor buffer ring
+
+\item [DOM0\_PINCPUDOMAIN:] pin domain to a particular CPU
+
+\item [DOM0\_TBUFCONTROL:] get and set trace buffer attributes
+
+\item [DOM0\_PHYSINFO:] get information about the host machine
+
+\item [DOM0\_SCHED\_ID:] get the ID of the current Xen scheduler
+
+\item [DOM0\_SHADOW\_CONTROL:] switch between shadow page-table modes
+
+\item [DOM0\_SETDOMAINMAXMEM:] set maximum memory allocation of a domain
+
+\item [DOM0\_GETPAGEFRAMEINFO2:] batched interface for getting
 page frame info
 
-\item [\it DOM0\_ADD\_MEMTYPE:] set MTRRs
-
-\item [\it DOM0\_DEL\_MEMTYPE:] remove a memory type range
-
-\item [\it DOM0\_READ\_MEMTYPE:] read MTRR
-
-\item [\it DOM0\_PERFCCONTROL:] control Xen's software performance
+\item [DOM0\_ADD\_MEMTYPE:] set MTRRs
+
+\item [DOM0\_DEL\_MEMTYPE:] remove a memory type range
+
+\item [DOM0\_READ\_MEMTYPE:] read MTRR
+
+\item [DOM0\_PERFCCONTROL:] control Xen's software performance
 counters
 
-\item [\it DOM0\_MICROCODE:] update CPU microcode
-
-\item [\it DOM0\_IOPORT\_PERMISSION:] modify domain permissions for an
+\item [DOM0\_MICROCODE:] update CPU microcode
+
+\item [DOM0\_IOPORT\_PERMISSION:] modify domain permissions for an
 IO port range (enable / disable a range for a particular domain)
 
-\item [\it DOM0\_GETVCPUCONTEXT:] get context from a VCPU
-
-\item [\it DOM0\_GETVCPUINFO:] get current state for a VCPU
-\item [\it DOM0\_GETDOMAININFOLIST:] batched interface to get domain
+\item [DOM0\_GETVCPUCONTEXT:] get context from a VCPU
+
+\item [DOM0\_GETVCPUINFO:] get current state for a VCPU
+\item [DOM0\_GETDOMAININFOLIST:] batched interface to get domain
 info
 
-\item [\it DOM0\_PLATFORM\_QUIRK:] inform Xen of a platform quirk it
+\item [DOM0\_PLATFORM\_QUIRK:] inform Xen of a platform quirk it
 needs to handle (e.g. noirqbalance)
 
-\item [\it DOM0\_PHYSICAL\_MEMORY\_MAP:] get info about dom0's memory
+\item [DOM0\_PHYSICAL\_MEMORY\_MAP:] get info about dom0's memory
 map
 
-\item [\it DOM0\_MAX\_VCPUS:] change max number of VCPUs for a domain
-
-\item [\it DOM0\_SETDOMAINHANDLE:] set the handle for a domain
+\item [DOM0\_MAX\_VCPUS:] change max number of VCPUs for a domain
+
+\item [DOM0\_SETDOMAINHANDLE:] set the handle for a domain
 
 \end{description} 
 \end{quote} 
@@ -2172,20 +2198,20 @@
 
 Use Xen to interact with the console; operations are:
 
-{\it CONSOLEIO\_write}: Output count characters from buffer str.
-
-{\it CONSOLEIO\_read}: Input at most count characters into buffer str.
+{CONSOLEIO\_write}: Output count characters from buffer str.
+
+{CONSOLEIO\_read}: Input at most count characters into buffer str.
 \end{quote} 
 
 A pair of hypercalls allows access to the underlying debug registers: 
 \begin{quote}
 \hypercall{set\_debugreg(int reg, unsigned long value)}
 
-Set debug register {\tt reg} to {\tt value} 
+Set debug register {\bf reg} to {\bf value} 
 
 \hypercall{get\_debugreg(int reg)}
 
-Return the contents of the debug register {\tt reg}
+Return the contents of the debug register {\bf reg}
 \end{quote}
 
 And finally: 
diff -r e04978011d2d -r 25003dd43a92 extras/mini-os/Makefile
--- a/extras/mini-os/Makefile   Fri Mar 17 21:26:24 2006
+++ b/extras/mini-os/Makefile   Fri Mar 17 22:37:28 2006
@@ -32,7 +32,7 @@
 OBJS += $(patsubst %.c,%.o,$(wildcard *.c))
 OBJS += $(patsubst %.c,%.o,$(wildcard lib/*.c))
 OBJS += $(patsubst %.c,%.o,$(wildcard xenbus/*.c))
-#OBJS += $(patsubst %.c,%.o,$(wildcard console/*.c))
+OBJS += $(patsubst %.c,%.o,$(wildcard console/*.c))
                                                                                
   
 HDRS := $(wildcard include/*.h)
 HDRS += $(wildcard include/xen/*.h)
diff -r e04978011d2d -r 25003dd43a92 extras/mini-os/events.c
--- a/extras/mini-os/events.c   Fri Mar 17 21:26:24 2006
+++ b/extras/mini-os/events.c   Fri Mar 17 22:37:28 2006
@@ -21,6 +21,7 @@
 #include <hypervisor.h>
 #include <events.h>
 #include <lib.h>
+
 
 static ev_action_t ev_actions[NR_EVS];
 void default_handler(int port, struct pt_regs *regs);
@@ -58,7 +59,7 @@
 
 int bind_evtchn( u32 port, void (*handler)(int, struct pt_regs *) )
 {
-       if(ev_actions[port].handler)
+       if(ev_actions[port].handler != default_handler)
         printk("WARN: Handler for port %d already registered, replacing\n",
                                port);
 
@@ -73,7 +74,7 @@
 
 void unbind_evtchn( u32 port )
 {
-       if (!ev_actions[port].handler)
+       if (ev_actions[port].handler)
                printk("WARN: No handler for port %d when unbinding\n", port);
        ev_actions[port].handler = NULL;
        ev_actions[port].status |= EVS_DISABLED;
diff -r e04978011d2d -r 25003dd43a92 extras/mini-os/include/lib.h
--- a/extras/mini-os/include/lib.h      Fri Mar 17 21:26:24 2006
+++ b/extras/mini-os/include/lib.h      Fri Mar 17 22:37:28 2006
@@ -56,13 +56,10 @@
 #define _LIB_H_
 
 #include <stdarg.h>
-
+#include <console.h>
 
 /* printing */
-#define printk  printf
-#define kprintf printf
 #define _p(_x) ((void *)(unsigned long)(_x))
-void printf(const char *fmt, ...);
 int vsnprintf(char *buf, size_t size, const char *fmt, va_list args);
 int vscnprintf(char *buf, size_t size, const char *fmt, va_list args);
 int snprintf(char * buf, size_t size, const char *fmt, ...);
diff -r e04978011d2d -r 25003dd43a92 extras/mini-os/kernel.c
--- a/extras/mini-os/kernel.c   Fri Mar 17 21:26:24 2006
+++ b/extras/mini-os/kernel.c   Fri Mar 17 22:37:28 2006
@@ -76,6 +76,8 @@
 }
 
 
+extern void init_console(void);
+
 /*
  * INITIAL C ENTRY POINT.
  */
@@ -127,15 +129,19 @@
 
     /* set up events */
     init_events();
+    
     /* init time and timers */
     init_time();
-    
+
+    /* init the console driver */
+    init_console();
+
     /* init scheduler */
     init_sched();
 
     /* init xenbus */
     xs_init();
-    
+   
     /* Everything initialised, start idle thread */
     run_idle_thread();
 }
diff -r e04978011d2d -r 25003dd43a92 extras/mini-os/lib/printf.c
--- a/extras/mini-os/lib/printf.c       Fri Mar 17 21:26:24 2006
+++ b/extras/mini-os/lib/printf.c       Fri Mar 17 22:37:28 2006
@@ -556,19 +556,6 @@
     return i;
 }
 
-
-void printf(const char *fmt, ...)
-{
-    static char   buf[1024];
-    va_list       args;
-    
-    va_start(args, fmt);
-    (void)vsnprintf(buf, sizeof(buf), fmt, args);
-    va_end(args);        
-   
-    (void)HYPERVISOR_console_io(CONSOLEIO_write, strlen(buf), buf);
-}
-
 /**
  * vsscanf - Unformat a buffer into a list of arguments
  * @buf:       input buffer
diff -r e04978011d2d -r 25003dd43a92 extras/mini-os/mm.c
--- a/extras/mini-os/mm.c       Fri Mar 17 21:26:24 2006
+++ b/extras/mini-os/mm.c       Fri Mar 17 22:37:28 2006
@@ -380,6 +380,10 @@
            "prev_l_mfn=%lx, offset=%lx\n", 
            level, *pt_pfn, prev_l_mfn, offset);
 
+    /* We need to clear the page, otherwise we might fail to map it
+       as a page table page */
+    memset((unsigned long*)pfn_to_virt(*pt_pfn), 0, PAGE_SIZE);  
+ 
     if (level == L1_FRAME)
     {
          prot_e = L1_PROT;
diff -r e04978011d2d -r 25003dd43a92 extras/mini-os/sched.c
--- a/extras/mini-os/sched.c    Fri Mar 17 21:26:24 2006
+++ b/extras/mini-os/sched.c    Fri Mar 17 22:37:28 2006
@@ -46,6 +46,7 @@
 #include <sched.h>
 #include <semaphore.h>
 
+
 #ifdef SCHED_DEBUG
 #define DEBUG(_f, _a...) \
     printk("MINI_OS(file=sched.c, line=%d) " _f "\n", __LINE__, ## _a)
@@ -61,7 +62,7 @@
 #define clear_runnable(_thread) (_thread->flags &= ~RUNNABLE_FLAG)
 
 
-struct thread *idle_thread;
+struct thread *idle_thread = NULL;
 LIST_HEAD(exited_threads);
 
 void dump_stack(struct thread *thread)
@@ -225,7 +226,6 @@
     for(;;)
     {
         schedule();
-        printk("Blocking the domain\n"); 
         block_domain(10000);
     }
 }
diff -r e04978011d2d -r 25003dd43a92 
linux-2.6-xen-sparse/arch/i386/mm/pgtable-xen.c
--- a/linux-2.6-xen-sparse/arch/i386/mm/pgtable-xen.c   Fri Mar 17 21:26:24 2006
+++ b/linux-2.6-xen-sparse/arch/i386/mm/pgtable-xen.c   Fri Mar 17 22:37:28 2006
@@ -587,6 +587,8 @@
 
 void mm_pin(struct mm_struct *mm)
 {
+       if (xen_feature(XENFEAT_writable_page_tables))
+           return;
        spin_lock(&mm->page_table_lock);
        __pgd_pin(mm->pgd);
        spin_unlock(&mm->page_table_lock);
@@ -594,6 +596,8 @@
 
 void mm_unpin(struct mm_struct *mm)
 {
+       if (xen_feature(XENFEAT_writable_page_tables))
+           return;
        spin_lock(&mm->page_table_lock);
        __pgd_unpin(mm->pgd);
        spin_unlock(&mm->page_table_lock);
@@ -602,6 +606,8 @@
 void mm_pin_all(void)
 {
        struct page *page;
+       if (xen_feature(XENFEAT_writable_page_tables))
+           return;
        for (page = pgd_list; page; page = (struct page *)page->index) {
                if (!test_bit(PG_pinned, &page->flags))
                        __pgd_pin((pgd_t *)page_address(page));
diff -r e04978011d2d -r 25003dd43a92 
linux-2.6-xen-sparse/arch/x86_64/mm/pageattr-xen.c
--- a/linux-2.6-xen-sparse/arch/x86_64/mm/pageattr-xen.c        Fri Mar 17 
21:26:24 2006
+++ b/linux-2.6-xen-sparse/arch/x86_64/mm/pageattr-xen.c        Fri Mar 17 
22:37:28 2006
@@ -71,6 +71,9 @@
 
 void mm_pin(struct mm_struct *mm)
 {
+       if (xen_feature(XENFEAT_writable_page_tables))
+               return;
+
        spin_lock(&mm->page_table_lock);
 
        mm_walk(mm, PAGE_KERNEL_RO);
@@ -94,6 +97,9 @@
 
 void mm_unpin(struct mm_struct *mm)
 {
+       if (xen_feature(XENFEAT_writable_page_tables))
+               return;
+
        spin_lock(&mm->page_table_lock);
 
        xen_pgd_unpin(__pa(mm->pgd));
@@ -116,6 +122,9 @@
 
 void mm_pin_all(void)
 {
+       if (xen_feature(XENFEAT_writable_page_tables))
+               return;
+
        while (!list_empty(&mm_unpinned))       
                mm_pin(list_entry(mm_unpinned.next, struct mm_struct,
                                  context.unpinned));
diff -r e04978011d2d -r 25003dd43a92 
linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c
--- a/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c Fri Mar 17 21:26:24 2006
+++ b/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c Fri Mar 17 22:37:28 2006
@@ -116,15 +116,13 @@
                         const struct xenbus_device_id *id)
 {
        int err;
-       struct backend_info *be = kmalloc(sizeof(struct backend_info),
+       struct backend_info *be = kzalloc(sizeof(struct backend_info),
                                          GFP_KERNEL);
        if (!be) {
                xenbus_dev_fatal(dev, -ENOMEM,
                                 "allocating backend structure");
                return -ENOMEM;
        }
-       memset(be, 0, sizeof(*be));
-
        be->dev = dev;
        dev->data = be;
 
diff -r e04978011d2d -r 25003dd43a92 
linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c
--- a/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c      Fri Mar 17 
21:26:24 2006
+++ b/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c      Fri Mar 17 
22:37:28 2006
@@ -90,13 +90,12 @@
                return err;
        }
 
-       info = kmalloc(sizeof(*info), GFP_KERNEL);
+       info = kzalloc(sizeof(*info), GFP_KERNEL);
        if (!info) {
                xenbus_dev_fatal(dev, -ENOMEM, "allocating info structure");
                return -ENOMEM;
        }
 
-       memset(info, 0, sizeof(*info));
        info->xbdev = dev;
        info->vdevice = vdevice;
        info->connected = BLKIF_STATE_DISCONNECTED;
diff -r e04978011d2d -r 25003dd43a92 
linux-2.6-xen-sparse/drivers/xen/blkfront/vbd.c
--- a/linux-2.6-xen-sparse/drivers/xen/blkfront/vbd.c   Fri Mar 17 21:26:24 2006
+++ b/linux-2.6-xen-sparse/drivers/xen/blkfront/vbd.c   Fri Mar 17 22:37:28 2006
@@ -97,11 +97,9 @@
 {
        struct xlbd_major_info *ptr;
 
-       ptr = kmalloc(sizeof(struct xlbd_major_info), GFP_KERNEL);
+       ptr = kzalloc(sizeof(struct xlbd_major_info), GFP_KERNEL);
        if (ptr == NULL)
                return NULL;
-
-       memset(ptr, 0, sizeof(struct xlbd_major_info));
 
        ptr->major = major;
 
diff -r e04978011d2d -r 25003dd43a92 
linux-2.6-xen-sparse/drivers/xen/blktap/xenbus.c
--- a/linux-2.6-xen-sparse/drivers/xen/blktap/xenbus.c  Fri Mar 17 21:26:24 2006
+++ b/linux-2.6-xen-sparse/drivers/xen/blktap/xenbus.c  Fri Mar 17 22:37:28 2006
@@ -141,12 +141,11 @@
        char *frontend;
        int err;
 
-       be = kmalloc(sizeof(*be), GFP_KERNEL);
+       be = kzalloc(sizeof(*be), GFP_KERNEL);
        if (!be) {
                xenbus_dev_error(dev, -ENOMEM, "allocating backend structure");
                return -ENOMEM;
        }
-       memset(be, 0, sizeof(*be));
 
        frontend = NULL;
        err = xenbus_gather(dev->nodename,
diff -r e04978011d2d -r 25003dd43a92 
linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c
--- a/linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c Fri Mar 17 21:26:24 2006
+++ b/linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c Fri Mar 17 22:37:28 2006
@@ -76,14 +76,13 @@
                         const struct xenbus_device_id *id)
 {
        int err;
-       struct backend_info *be = kmalloc(sizeof(struct backend_info),
+       struct backend_info *be = kzalloc(sizeof(struct backend_info),
                                          GFP_KERNEL);
        if (!be) {
                xenbus_dev_fatal(dev, -ENOMEM,
                                 "allocating backend structure");
                return -ENOMEM;
        }
-       memset(be, 0, sizeof(*be));
 
        be->dev = dev;
        dev->data = be;
diff -r e04978011d2d -r 25003dd43a92 
linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c
--- a/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c      Fri Mar 17 
21:26:24 2006
+++ b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c      Fri Mar 17 
22:37:28 2006
@@ -845,11 +845,11 @@
        }
 
        while ((skb = __skb_dequeue(&rxq)) != NULL) {
-               if (skb->len > (dev->mtu + ETH_HLEN)) {
+               if (skb->len > (dev->mtu + ETH_HLEN + 4)) {
                        if (net_ratelimit())
                                printk(KERN_INFO "Received packet too big for "
                                       "MTU (%d > %d)\n",
-                                      skb->len - ETH_HLEN, dev->mtu);
+                                      skb->len - ETH_HLEN - 4, dev->mtu);
                        skb->len  = 0;
                        skb->tail = skb->data;
                        init_skb_shinfo(skb);
diff -r e04978011d2d -r 25003dd43a92 
linux-2.6-xen-sparse/drivers/xen/pcifront/pci_op.c
--- a/linux-2.6-xen-sparse/drivers/xen/pcifront/pci_op.c        Fri Mar 17 
21:26:24 2006
+++ b/linux-2.6-xen-sparse/drivers/xen/pcifront/pci_op.c        Fri Mar 17 
22:37:28 2006
@@ -8,6 +8,7 @@
 #include <linux/init.h>
 #include <linux/pci.h>
 #include <linux/spinlock.h>
+#include <linux/time.h>
 #include <xen/evtchn.h>
 #include "pcifront.h"
 
@@ -40,8 +41,10 @@
 {
        int err = 0;
        struct xen_pci_op *active_op = &pdev->sh_info->op;
-       unsigned long irq_flags, poll_end;
+       unsigned long irq_flags;
        evtchn_port_t port = pdev->evtchn;
+       nsec_t ns, ns_timeout;
+       struct timeval tv;
 
        spin_lock_irqsave(&pdev->sh_info_lock, irq_flags);
 
@@ -52,15 +55,25 @@
        set_bit(_XEN_PCIF_active, (unsigned long *)&pdev->sh_info->flags);
        notify_remote_via_evtchn(port);
 
-       poll_end = jiffies + 5*HZ;
+       /*
+        * We set a poll timeout of 5 seconds but give up on return after
+        * 4 seconds. It is better to time out too late rather than too early
+        * (in the latter case we end up continually re-executing poll() with a
+        * timeout in the past). 1s difference gives plenty of slack for error.
+        */
+       do_gettimeofday(&tv);
+       ns_timeout = timeval_to_ns(&tv) + 4 * (nsec_t)NSEC_PER_SEC;
+
        clear_evtchn(port);
 
        while (test_bit(_XEN_PCIF_active,
                        (unsigned long *)&pdev->sh_info->flags)) {
-               if (HYPERVISOR_poll(&port, 1, poll_end))
+               if (HYPERVISOR_poll(&port, 1, jiffies + 5*HZ))
                        BUG();
                clear_evtchn(port);
-               if (time_after(jiffies, poll_end)) {
+               do_gettimeofday(&tv);
+               ns = timeval_to_ns(&tv);
+               if (ns > ns_timeout) {
                        dev_err(&pdev->xdev->dev,
                                "pciback not responding!!!\n");
                        clear_bit(_XEN_PCIF_active,
diff -r e04978011d2d -r 25003dd43a92 
linux-2.6-xen-sparse/drivers/xen/tpmback/xenbus.c
--- a/linux-2.6-xen-sparse/drivers/xen/tpmback/xenbus.c Fri Mar 17 21:26:24 2006
+++ b/linux-2.6-xen-sparse/drivers/xen/tpmback/xenbus.c Fri Mar 17 22:37:28 2006
@@ -67,7 +67,7 @@
                          const struct xenbus_device_id *id)
 {
        int err;
-       struct backend_info *be = kmalloc(sizeof(struct backend_info),
+       struct backend_info *be = kzalloc(sizeof(struct backend_info),
                                          GFP_KERNEL);
 
        if (!be) {
@@ -75,8 +75,6 @@
                                 "allocating backend structure");
                return -ENOMEM;
        }
-
-       memset(be, 0, sizeof(*be));
 
        be->is_instance_set = 0;
        be->dev = dev;
diff -r e04978011d2d -r 25003dd43a92 
linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.c
--- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.c    Fri Mar 17 
21:26:24 2006
+++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.c    Fri Mar 17 
22:37:28 2006
@@ -106,8 +106,10 @@
                cons = intf->req_cons;
                prod = intf->req_prod;
                mb();
-               if (!check_indexes(cons, prod))
+               if (!check_indexes(cons, prod)) {
+                       intf->req_cons = intf->req_prod = 0;
                        return -EIO;
+               }
 
                dst = get_output_chunk(cons, prod, intf->req, &avail);
                if (avail == 0)
@@ -150,8 +152,10 @@
                cons = intf->rsp_cons;
                prod = intf->rsp_prod;
                mb();
-               if (!check_indexes(cons, prod))
+               if (!check_indexes(cons, prod)) {
+                       intf->rsp_cons = intf->rsp_prod = 0;
                        return -EIO;
+               }
 
                src = get_input_chunk(cons, prod, intf->rsp, &avail);
                if (avail == 0)
diff -r e04978011d2d -r 25003dd43a92 
linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_dev.c
--- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_dev.c      Fri Mar 17 
21:26:24 2006
+++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_dev.c      Fri Mar 17 
22:37:28 2006
@@ -179,11 +179,10 @@
 
        nonseekable_open(inode, filp);
 
-       u = kmalloc(sizeof(*u), GFP_KERNEL);
+       u = kzalloc(sizeof(*u), GFP_KERNEL);
        if (u == NULL)
                return -ENOMEM;
 
-       memset(u, 0, sizeof(*u));
        INIT_LIST_HEAD(&u->transactions);
        init_waitqueue_head(&u->read_waitq);
 
diff -r e04978011d2d -r 25003dd43a92 
linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c
--- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c    Fri Mar 17 
21:26:24 2006
+++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c    Fri Mar 17 
22:37:28 2006
@@ -552,10 +552,9 @@
        }
 
        stringlen = strlen(nodename) + 1 + strlen(type) + 1;
-       xendev = kmalloc(sizeof(*xendev) + stringlen, GFP_KERNEL);
+       xendev = kzalloc(sizeof(*xendev) + stringlen, GFP_KERNEL);
        if (!xendev)
                return -ENOMEM;
-       memset(xendev, 0, sizeof(*xendev));
 
        /* Copy the strings into the extra space. */
 
diff -r e04978011d2d -r 25003dd43a92 
linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c
--- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c       Fri Mar 17 
21:26:24 2006
+++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c       Fri Mar 17 
22:37:28 2006
@@ -237,7 +237,14 @@
                return ERR_PTR(-err);
        }
 
-       BUG_ON(msg.type != type);
+       if (msg.type != type) {
+               if (printk_ratelimit())
+                       printk(KERN_WARNING
+                              "XENBUS unexpected type [%d], expected [%d]\n",
+                              msg.type, type);
+               kfree(ret);
+               return ERR_PTR(-EINVAL);
+       }
        return ret;
 }
 
diff -r e04978011d2d -r 25003dd43a92 tools/ioemu/configure
--- a/tools/ioemu/configure     Fri Mar 17 21:26:24 2006
+++ b/tools/ioemu/configure     Fri Mar 17 22:37:28 2006
@@ -238,6 +238,29 @@
 
 fi
 
+if test "$vnc" = "yes" ; then
+
+# check for eager event handling
+cat > $TMPC <<EOF
+#include "rfb/rfb.h"
+int main(void) {
+       rfbScreenInfoPtr screen;
+
+       screen->handleEventsEagerly = 1;
+}
+EOF
+
+if $cc `libvncserver-config --cflags` -o $TMPO $TMPC 2> /dev/null ; then
+   have_eager_events="yes"
+else
+   echo "!!"
+   echo "!! Slow VNC mouse, LibVNCServer doesn't support eager events"
+   echo "!!"
+   have_eager_events="no"
+fi
+
+fi
+
 ##########################################
 # SDL probe
 
@@ -472,6 +495,9 @@
     vnc_cflags="/usr/include"
   fi
   echo "VNC_CFLAGS=$vnc_cflags" >> $config_mak
+  if test "$have_eager_events" = "yes" ; then
+    echo "#define VNC_EAGER_EVENTS 1" >> $config_h
+  fi
 fi
 
 if test "$sdl" = "yes"; then
diff -r e04978011d2d -r 25003dd43a92 tools/ioemu/hw/pckbd.c
--- a/tools/ioemu/hw/pckbd.c    Fri Mar 17 21:26:24 2006
+++ b/tools/ioemu/hw/pckbd.c    Fri Mar 17 22:37:28 2006
@@ -29,9 +29,6 @@
 /* debug PC keyboard : only mouse */
 //#define DEBUG_MOUSE
 
-/* enable synapatic touchpad device model */
-//#define SYNAPTIC
-
 /*     Keyboard Controller Commands */
 #define KBD_CCMD_READ_MODE     0x20    /* Read mode bits */
 #define KBD_CCMD_WRITE_MODE    0x60    /* Write mode bits */
@@ -114,18 +111,27 @@
 
 #define KBD_QUEUE_SIZE 256
 
+/*
+ * Summagraphics tablet defines
+ */
+#define SUMMA_BORDER   100
+#define SUMMA_MAXX     (16000 - 1)
+#define SUMMA_MAXY     (16000 - 1)
+
 typedef struct {
     uint8_t aux[KBD_QUEUE_SIZE];
     uint8_t data[KBD_QUEUE_SIZE];
     int rptr, wptr, count;
 } KBDQueue;
 
-#ifdef SYNAPTIC
-typedef struct {
-    int absolute;
-    int high;
-} TouchPad;
-#endif
+/*
+ *  Mouse types
+ */
+#define PS2    0
+#define IMPS2  3
+#define IMEX   4
+#define PAD    10
+#define TABLET 11
 
 typedef struct KBDState {
     KBDQueue queue;
@@ -143,16 +149,19 @@
     uint8_t mouse_wrap;
     uint8_t mouse_type; /* 0 = PS2, 3 = IMPS/2, 4 = IMEX */
     uint8_t mouse_detect_state;
+    int mouse_x;  /* absolute coordinates (for mousepad) */
+    int mouse_y;
     int mouse_dx; /* current values, needed for 'poll' mode */
     int mouse_dy;
     int mouse_dz;
     uint8_t mouse_buttons;
-#ifdef SYNAPTIC
-    TouchPad touchpad;
-#endif
+    CharDriverState *chr;
+    void *cookie;
 } KBDState;
 
 KBDState kbd_state;
+
+int summa_ok;          /* Allow Summagraphics emulation if true */
 
 /* update irq and KBD_STAT_[MOUSE_]OBF */
 /* XXX: not generating the irqs if KBD_MODE_DISABLE_KBD is set may be
@@ -398,7 +407,9 @@
     }
 }
 
-static void kbd_mouse_send_packet(KBDState *s)
+int mouse_maxx, mouse_maxy;
+
+static int kbd_mouse_send_packet(KBDState *s)
 {
     unsigned int b;
     int dx1, dy1, dz1;
@@ -406,95 +417,73 @@
     dx1 = s->mouse_dx;
     dy1 = s->mouse_dy;
     dz1 = s->mouse_dz;
-#ifdef SYNAPTIC
-    if (s->touchpad.absolute)
-    {
-       int dz2, dleftnright, dg, df;
-       if (dx1 > 6143)
-           dx1 = 6143;
-       else if (dx1 < 0)
-           dx1 = 0;
-       if (dy1 > 6143)
-           dy1 = 6143;
-       else if (dy1 < 0)
-           dy1 = 0;
-       dz2 = 80; /* normal finger pressure */
-       dg = 0; /* guesture not supported */
-       df = 0; /* finger not supported */
-       dleftnright = (s->mouse_buttons & 0x07);
-       /*
-       X: 13 bits --return absolute x ord
-       Y: 13 bits --return absolute y ord
-       Z: 8 bits --return constant 80 since we don't know how hard the user
-               is pressing on the mouse button ;) 80 is the default for pen
-               pressure, as touchpads cant sense what pressure a pen makes.
-       W: 4 bits --return 0, we don't support finger width (should we?)
-       left: 1 bit --is left button pressed
-       right: 1 bit --is right button pressed
-       guesture: 1 bit --we dont support, return 0
-       finger: 1 bit --ditto
-       total: 42 bits in 6 bytes
-       note that Synaptics drivers ignore the finger and guesture bits and
-       consider them redundant
-       */
-       /*
-       note: the packet setup is different when Wmode = 1, but
-           this doesn't apply since we don't support Wmode capability
-       format of packet is as follows:
-       */
-       // 1 0 finger reserved 0 gesture right left
-       kbd_queue(s, (0x80 | (df ? 0x20 : 0) | (dg ? 0x04 : 0) | dleftnright), 
1);
-       kbd_queue(s, ((dy1 & 0xF) * 256) + (dx1 & 0xF), 1);
-       kbd_queue(s, 80, 1); //byte 3
-       // 1 1 y-12 x-12 0 gesture right left
-       kbd_queue(s, (0xC0 | ((dy1 & 1000) ? 0x20 : 0) | ((dx1 & 1000) ? 0x10 : 
0) | (dg ? 0x04 : 0) | dleftnright), 1);
-       kbd_queue(s, dx1 & 0xFF, 1);
-       kbd_queue(s, dy1 & 0xFF, 1);
-       return;
-    }
-#endif
-    /* XXX: increase range to 8 bits ? */
-    if (dx1 > 127)
-        dx1 = 127;
-    else if (dx1 < -127)
-        dx1 = -127;
-    if (dy1 > 127)
-        dy1 = 127;
-    else if (dy1 < -127)
-        dy1 = -127;
-    b = 0x08 | ((dx1 < 0) << 4) | ((dy1 < 0) << 5) | (s->mouse_buttons & 0x07);
-    kbd_queue(s, b, 1);
-    kbd_queue(s, dx1 & 0xff, 1);
-    kbd_queue(s, dy1 & 0xff, 1);
-    /* extra byte for IMPS/2 or IMEX */
     switch(s->mouse_type) {
-    default:
-        break;
-    case 3:
-        if (dz1 > 127)
-            dz1 = 127;
-        else if (dz1 < -127)
-                dz1 = -127;
-        kbd_queue(s, dz1 & 0xff, 1);
-        break;
-    case 4:
-        if (dz1 > 7)
-            dz1 = 7;
-        else if (dz1 < -7)
-            dz1 = -7;
-        b = (dz1 & 0x0f) | ((s->mouse_buttons & 0x18) << 1);
-        kbd_queue(s, b, 1);
-        break;
-    }
-
-    /* update deltas */
-    s->mouse_dx -= dx1;
-    s->mouse_dy -= dy1;
-    s->mouse_dz -= dz1;
+  
+    case TABLET:        /* Summagraphics pen tablet */
+       dx1 = s->mouse_x;
+       dy1 = s->mouse_y;
+       dx1 = ((dx1 * SUMMA_MAXX) / mouse_maxx) + SUMMA_BORDER;
+       dy1 = ((dy1 * SUMMA_MAXY) / mouse_maxy) + SUMMA_BORDER;
+       ser_queue(s->cookie, 0x80 | (s->mouse_buttons & 7));
+       ser_queue(s->cookie, dx1 & 0x7f);
+       ser_queue(s->cookie, dx1 >> 7);
+       ser_queue(s->cookie, dy1 & 0x7f);
+       ser_queue(s->cookie, dy1 >> 7);
+       s->mouse_dx = 0; 
+       s->mouse_dy = 0;
+       s->mouse_dz = 0;
+       return 0;
+
+    default:   /* PS/2 style mice */
+       /* XXX: increase range to 8 bits ? */
+       if (dx1 > 127)
+           dx1 = 127;
+       else if (dx1 < -127)
+           dx1 = -127;
+       if (dy1 > 127)
+           dy1 = 127;
+       else if (dy1 < -127)
+           dy1 = -127;
+       b = 0x08 | ((dx1 < 0) << 4) | ((dy1 < 0) << 5) | (s->mouse_buttons & 
0x07);
+       kbd_queue(s, b, 1);
+       kbd_queue(s, dx1 & 0xff, 1);
+       kbd_queue(s, dy1 & 0xff, 1);
+       /* extra byte for IMPS/2 or IMEX */
+       switch(s->mouse_type) {
+
+       default:
+           break;
+
+       case IMPS2:
+           if (dz1 > 127)
+               dz1 = 127;
+           else if (dz1 < -127)
+               dz1 = -127;
+           kbd_queue(s, dz1 & 0xff, 1);
+           break;
+
+       case IMEX:
+           if (dz1 > 7)
+               dz1 = 7;
+           else if (dz1 < -7)
+               dz1 = -7;
+           b = (dz1 & 0x0f) | ((s->mouse_buttons & 0x18) << 1);
+           kbd_queue(s, b, 1);
+           break;
+       }
+
+       /* update deltas */
+       s->mouse_dx -= dx1;
+       s->mouse_dy -= dy1;
+       s->mouse_dz -= dz1;
+       return s->mouse_dx || s->mouse_dy || s->mouse_dz;
+
+    }
 }
 
 static void pc_kbd_mouse_event(void *opaque, 
-                               int dx, int dy, int dz, int buttons_state)
+                               int dx, int dy, int dz, int buttons_state,
+                              int x, int y)
 {
     KBDState *s = opaque;
 
@@ -502,6 +491,8 @@
     if (!(s->mouse_status & MOUSE_STATUS_ENABLED))
         return;
 
+    s->mouse_x = x;
+    s->mouse_y = y;
     s->mouse_dx += dx;
     s->mouse_dy -= dy;
     s->mouse_dz += dz;
@@ -513,23 +504,76 @@
     
     if (!(s->mouse_status & MOUSE_STATUS_REMOTE) &&
         (s->queue.count < (KBD_QUEUE_SIZE - 16))) {
-        for(;;) {
-            /* if not remote, send event. Multiple events are sent if
-               too big deltas */
-            kbd_mouse_send_packet(s);
-            if (s->mouse_dx == 0 && s->mouse_dy == 0 && s->mouse_dz == 0)
-                break;
-        }
-    }
+               while (kbd_mouse_send_packet(s))
+                   ;
+    }
+}
+
+static void summa(KBDState *s, int val)
+{
+    static int summa = 0;
+
+    if (s->mouse_type == TABLET) {
+       switch (val) {
+
+       case '?':       /* read firmware ID */
+           ser_queue(s->cookie, '0');
+           break;
+
+       case 'a':       /* read config */
+           /*
+            *  Config looks like a movement packet but, because of scaling
+            *    issues we can't use `kbd_send_packet' to do this.
+            */
+           ser_queue(s->cookie, 0);
+           ser_queue(s->cookie, (SUMMA_MAXX & 0x7f));
+           ser_queue(s->cookie, (SUMMA_MAXX >> 7));
+           ser_queue(s->cookie, (SUMMA_MAXY & 0x7f));
+           ser_queue(s->cookie, (SUMMA_MAXY >> 7));
+           break;
+
+       default:        /* ignore all others */
+           break;
+
+       }
+       return;
+    }
+    if (val == 'B') {
+       summa++;
+       return;
+    } else if (summa && val == 'z') {
+       s->mouse_type = TABLET;
+       return;
+    }
+    summa = 0;
+    return;
+}
+
+int summa_write(CharDriverState *chr, const uint8_t *buf, int len)
+{
+    KBDState *s = (KBDState *)chr->opaque;
+    int n;
+
+    n = len;
+    while (n-- > 0)
+       summa(s, *buf++);
+    return len;
+}
+
+void summa_init(void *cookie, CharDriverState *chr)
+{
+
+    if (summa_ok == 0)
+       return;
+    kbd_state.chr = chr;
+    kbd_state.cookie = (void *)cookie;
+    chr->chr_write = summa_write;
+    chr->opaque = (void *)&kbd_state;
+    return;
 }
 
 static void kbd_write_mouse(KBDState *s, int val)
 {
-#ifdef SYNAPTIC
-/* variables needed to store synaptics command info */
-static int rr = 0, ss = 0, tt = 0, uu = 0, res_count = 0, last_com = 0;
-int spare;
-#endif
 #ifdef DEBUG_MOUSE
     printf("kbd: write mouse 0x%02x\n", val);
 #endif
@@ -547,9 +591,6 @@
                 return;
             }
         }
-#ifdef SYNAPTIC
-       last_com = val;
-#endif
         switch(val) {
         case AUX_SET_SCALE11:
             s->mouse_status &= ~MOUSE_STATUS_SCALE21;
@@ -581,121 +622,6 @@
             kbd_queue(s, AUX_ACK, 1);
             break;
         case AUX_GET_SCALE:
-#ifdef SYNAPTIC
-           if (res_count == 4)
-           {
-                   /* time for the special stuff */
-                   kbd_queue(s, AUX_ACK, 1);
-                   /* below is how we get the real synaptic command */
-                   val = (rr*64) + (ss*16) + (tt*4) + uu;
-                   switch(val)
-                   {
-                           /* id touchpad */
-                           case 0x00:
-                                   /* info Minor */
-                                   kbd_queue(s, 0x00, 1);
-                                   /* special verification byte */
-                                   kbd_queue(s, 0x47, 1);
-                                   /* info Major * 0x10 + Info ModelCode*/
-                                   kbd_queue(s, 4 * 0x10 + 0, 1);
-                                   break;
-                                   /* read touchpad modes */
-                           case 0x01:
-                                   /* special verification byte */
-                                   kbd_queue(s, 0x3B, 1);
-                                   /* mode */
-                                   /*
-                                       bit 7 - absolute or relative position
-                                       bit 6 - 0 for 40 packets/sec, 1 for 80 
pack/sec
-                                       bit 3 - 1 for sleep mode, 0 for normal
-                                       bit 2 - 1 to detect tap/drag, 0 to 
disable
-                                       bit 1 - packet size, only valid for 
serial protocol
-                                       bit 0 - 0 for normal packets, 1 for 
enhanced packets
-                                       (absolute mode packets which have 
finger width)
-                                       */
-                                   if (s->touchpad.absolute && 
s->touchpad.high)
-                                   {
-                                           spare = 0xC0;
-                                   }
-                                   else if (s->touchpad.absolute)
-                                   {
-                                           spare = 0x80;
-                                   }
-                                   else if (s->touchpad.high)
-                                   {
-                                           spare = 0x40;
-                                   }
-                                   else
-                                   {
-                                           spare = 0x00;
-                                   }
-                                   kbd_queue(s, spare, 1);
-                                   /* special verification byte */
-                                   kbd_queue(s, 0x47, 1);
-                                   break;
-                                   /* read touchpad capabilites */
-                           case 0x02:
-                                   /* extended capability first 8 bits */
-                                   kbd_queue(s, 0x00, 1);
-                                   /* special verification byte */
-                                   kbd_queue(s, 0x47, 1);
-                                   /* extended capability last 8 bits */
-                                   kbd_queue(s, 0x00, 1);
-                                   /* basicly, we don't have any capabilites 
;0 */
-                                   break;
-                                   /* read model id */
-                           case 0x03:
-                                   /*
-                                       bit 23 = 0 (1 for upsidedownpad)
-                                       bit 22 = 0 (1 for 90 degree rotated pad)
-                                       bits 21-16 = 1 (standard model)
-                                       bits 15-9 = ??? (reserved for synaptics 
use)
-                                       bit 7 = 1
-                                       bit 6 = 0 (1 for sensing pens)
-                                       bit 5 = 1
-                                       bits 3-0 = 1 (rectangular geometery)
-                                   */
-                                   kbd_queue(s, 0xFC, 1);
-                                   kbd_queue(s, 0x00, 1);
-                                   kbd_queue(s, 0xF5, 1); //F7 for sensing pens
-                                   break;
-                                   /* read serial number prefix */
-                           case 0x06:
-                                   /* strange how they have this query even 
though
-                                       no touchpad actually has serial numbers 
*/
-                                   /* return serial prefix of 0 if we dont 
have one */
-                                   kbd_queue(s, 0x00, 1);
-                                   kbd_queue(s, 0x00, 1);
-                                   kbd_queue(s, 0x00, 1);
-                                   break;
-                                   /* read serial number suffix */
-                           case 0x07:
-                                   /* undefined if we dont have a valid serial 
prefix */
-                                   kbd_queue(s, 0x00, 1);
-                                   kbd_queue(s, 0x00, 1);
-                                   kbd_queue(s, 0x00, 1);
-                                   break;
-                                   /* read resolutions */
-                           case 0x08:
-                                   /* going to go with infoSensor = 1 
(Standard model) here */
-                                   /* absolute X in abolute units per mm */
-                                   kbd_queue(s, 85, 1);
-                                   /* undefined but first bit 7 will be set to 
1...
-                                       hell I'm going to set them all to 1 */
-                                   kbd_queue(s, 0xFF, 1);
-                                   /* absolute Y in abolute units per mm */
-                                   kbd_queue(s, 94, 1);
-                                   break;
-                           default:
-                                   /* invalid commands return undefined data */
-                                   kbd_queue(s, 0x00, 1);
-                                   kbd_queue(s, 0x00, 1);
-                                   kbd_queue(s, 0x00, 1);
-                                   break;
-                   }
-           }
-           else
-#endif
            {
                    /* not a special command, just do the regular stuff */
             kbd_queue(s, AUX_ACK, 1);
@@ -720,18 +646,12 @@
             s->mouse_sample_rate = 100;
             s->mouse_resolution = 2;
             s->mouse_status = 0;
-#ifdef SYNAPTIC
-                   s->touchpad.absolute = 0;
-#endif
             kbd_queue(s, AUX_ACK, 1);
             break;
         case AUX_RESET:
             s->mouse_sample_rate = 100;
             s->mouse_resolution = 2;
             s->mouse_status = 0;
-#ifdef SYNAPTIC
-           s->touchpad.absolute = 0;
-#endif
             kbd_queue(s, AUX_ACK, 1);
             kbd_queue(s, 0xaa, 1);
             kbd_queue(s, s->mouse_type, 1);
@@ -741,15 +661,6 @@
         }
         break;
     case AUX_SET_SAMPLE:
-#ifdef SYNAPTIC
-       if (res_count == 4 && val == 0x14)
-       {
-               /* time for the special stuff */
-               /* below is how we get the real synaptic command */
-               val = (rr*64) + (ss*16) + (tt*4) + uu;
-               /* TODO: set the mode byte */
-       } else
-#endif
         s->mouse_sample_rate = val;
 #if 0
         /* detect IMPS/2 or IMEX */
@@ -769,12 +680,12 @@
             break;
         case 2:
             if (val == 80) 
-                s->mouse_type = 3; /* IMPS/2 */
+                s->mouse_type = IMPS2; /* IMPS/2 */
             s->mouse_detect_state = 0;
             break;
         case 3:
             if (val == 80) 
-                s->mouse_type = 4; /* IMEX */
+                s->mouse_type = IMEX; /* IMEX */
             s->mouse_detect_state = 0;
             break;
         }
@@ -783,36 +694,6 @@
         s->mouse_write_cmd = -1;
         break;
     case AUX_SET_RES:
-#ifdef SYNAPTIC
-       if (last_com != AUX_SET_RES)
-       {
-               /* if its not 4 in a row, its not a command */
-               /* FIXME: if we are set 8 of these in a row, or 12, or 16,
-                  or etc ... or 4^n commands, then the nth'd mode byte sent 
might
-                  still work. not sure if this is how things are suppose to be
-                  or not. */
-               res_count = 0;
-       }
-       res_count++;
-       if (res_count > 4) res_count = 4;
-       switch(res_count)
-               /* we need to save the val in the right spots to get the
-                  real command later */
-       {
-               case 1:
-                       break;
-                       rr = val;
-               case 2:
-                       ss = val;
-                       break;
-               case 3:
-                       tt = val;
-                       break;
-               case 4:
-                       uu = val;
-                       break;
-       }
-#endif
         s->mouse_resolution = val;
         kbd_queue(s, AUX_ACK, 1);
         s->mouse_write_cmd = -1;
@@ -881,23 +762,19 @@
     qemu_put_8s(f, &s->write_cmd);
     qemu_put_8s(f, &s->status);
     qemu_put_8s(f, &s->mode);
-    qemu_put_be32s(f, &s->kbd_write_cmd);
-    qemu_put_be32s(f, &s->scan_enabled);
-    qemu_put_be32s(f, &s->mouse_write_cmd);
+    qemu_put_be32s(f, (uint32_t *)&s->kbd_write_cmd);
+    qemu_put_be32s(f, (uint32_t *)&s->scan_enabled);
+    qemu_put_be32s(f, (uint32_t *)&s->mouse_write_cmd);
     qemu_put_8s(f, &s->mouse_status);
     qemu_put_8s(f, &s->mouse_resolution);
     qemu_put_8s(f, &s->mouse_sample_rate);
     qemu_put_8s(f, &s->mouse_wrap);
     qemu_put_8s(f, &s->mouse_type);
     qemu_put_8s(f, &s->mouse_detect_state);
-    qemu_put_be32s(f, &s->mouse_dx);
-    qemu_put_be32s(f, &s->mouse_dy);
-    qemu_put_be32s(f, &s->mouse_dz);
+    qemu_put_be32s(f, (uint32_t *)&s->mouse_dx);
+    qemu_put_be32s(f, (uint32_t *)&s->mouse_dy);
+    qemu_put_be32s(f, (uint32_t *)&s->mouse_dz);
     qemu_put_8s(f, &s->mouse_buttons);
-#ifdef SYNAPTIC
-    qemu_put_be32s(f, &s->touchpad.absolute);
-    qemu_put_be32s(f, &s->touchpad.high);
-#endif
 }
 
 static int kbd_load(QEMUFile* f, void* opaque, int version_id)
@@ -909,23 +786,19 @@
     qemu_get_8s(f, &s->write_cmd);
     qemu_get_8s(f, &s->status);
     qemu_get_8s(f, &s->mode);
-    qemu_get_be32s(f, &s->kbd_write_cmd);
-    qemu_get_be32s(f, &s->scan_enabled);
-    qemu_get_be32s(f, &s->mouse_write_cmd);
+    qemu_get_be32s(f, (uint32_t *)&s->kbd_write_cmd);
+    qemu_get_be32s(f, (uint32_t *)&s->scan_enabled);
+    qemu_get_be32s(f, (uint32_t *)&s->mouse_write_cmd);
     qemu_get_8s(f, &s->mouse_status);
     qemu_get_8s(f, &s->mouse_resolution);
     qemu_get_8s(f, &s->mouse_sample_rate);
     qemu_get_8s(f, &s->mouse_wrap);
     qemu_get_8s(f, &s->mouse_type);
     qemu_get_8s(f, &s->mouse_detect_state);
-    qemu_get_be32s(f, &s->mouse_dx);
-    qemu_get_be32s(f, &s->mouse_dy);
-    qemu_get_be32s(f, &s->mouse_dz);
+    qemu_get_be32s(f, (uint32_t *)&s->mouse_dx);
+    qemu_get_be32s(f, (uint32_t *)&s->mouse_dy);
+    qemu_get_be32s(f, (uint32_t *)&s->mouse_dz);
     qemu_get_8s(f, &s->mouse_buttons);
-#ifdef SYNAPTIC
-    qemu_get_be32s(f, &s->touchpad.absolute);
-    qemu_get_be32s(f, &s->touchpad.high);
-#endif
     return 0;
 }
 
@@ -933,6 +806,7 @@
 {
     KBDState *s = &kbd_state;
     
+    s->mouse_type = PS2;
     kbd_reset(s);
     register_savevm("pckbd", 0, 2, kbd_save, kbd_load, s);
     register_ioport_read(0x60, 1, 1, kbd_read_data, s);
diff -r e04978011d2d -r 25003dd43a92 tools/ioemu/hw/serial.c
--- a/tools/ioemu/hw/serial.c   Fri Mar 17 21:26:24 2006
+++ b/tools/ioemu/hw/serial.c   Fri Mar 17 22:37:28 2006
@@ -70,6 +70,11 @@
 #define UART_LSR_OE    0x02    /* Overrun error indicator */
 #define UART_LSR_DR    0x01    /* Receiver data ready */
 
+/*
+ * Size of ring buffer for characters to send to host
+ */
+#define MAXCHRS        256
+
 struct SerialState {
     uint8_t divider;
     uint8_t rbr; /* receive register */
@@ -84,11 +89,22 @@
        it can be reset while reading iir */
     int thr_ipending;
     int irq;
+    struct cbuf {
+           uint8_t buf[MAXCHRS];
+           int in;
+           int out;
+    } cbuf;
     CharDriverState *chr;
 };
 
 static void serial_update_irq(SerialState *s)
 {
+    if ((s->lsr & UART_LSR_DR) == 0 && s->cbuf.in != s->cbuf.out) {
+       s->rbr = s->cbuf.buf[s->cbuf.out++];
+       if (s->cbuf.out >= MAXCHRS)
+           s->cbuf.out = 0;
+       s->lsr |= UART_LSR_DR;
+    }
     if ((s->lsr & UART_LSR_DR) && (s->ier & UART_IER_RDI)) {
         s->iir = UART_IIR_RDI;
     } else if (s->thr_ipending && (s->ier & UART_IER_THRI)) {
@@ -220,6 +236,22 @@
     return ret;
 }
 
+void ser_queue(SerialState *s, unsigned char c)
+{
+    int n;
+
+    n = s->cbuf.in - s->cbuf.out;
+    if (n < 0)
+       n += MAXCHRS;
+    if (n < (MAXCHRS - 1)) {
+       s->cbuf.buf[s->cbuf.in++] = c;
+       if (s->cbuf.in >= MAXCHRS)
+           s->cbuf.in = 0;
+       serial_update_irq(s);
+    }
+    return;
+}
+
 static int serial_can_receive(SerialState *s)
 {
     return !(s->lsr & UART_LSR_DR);
@@ -227,6 +259,9 @@
 
 static void serial_receive_byte(SerialState *s, int ch)
 {
+#ifdef DEBUG_SERIAL
+    printf("serial: serial_receive_byte: ch=0x%02x\n", ch);
+#endif // DEBUG_SERIAL
     s->rbr = ch;
     s->lsr |= UART_LSR_DR;
     serial_update_irq(s);
@@ -266,6 +301,8 @@
     s = qemu_mallocz(sizeof(SerialState));
     if (!s)
         return NULL;
+    s->cbuf.in = 0;
+    s->cbuf.out = 0;
     s->irq = irq;
     s->lsr = UART_LSR_TEMT | UART_LSR_THRE;
     s->iir = UART_IIR_NO_INT;
@@ -273,6 +310,7 @@
     register_ioport_write(base, 8, 1, serial_ioport_write, s);
     register_ioport_read(base, 8, 1, serial_ioport_read, s);
     s->chr = chr;
+    summa_init(s, chr);
     qemu_chr_add_read_handler(chr, serial_can_receive1, serial_receive1, s);
     qemu_chr_add_event_handler(chr, serial_event);
     return s;
diff -r e04978011d2d -r 25003dd43a92 tools/ioemu/hw/vga.c
--- a/tools/ioemu/hw/vga.c      Fri Mar 17 21:26:24 2006
+++ b/tools/ioemu/hw/vga.c      Fri Mar 17 22:37:28 2006
@@ -1340,6 +1340,99 @@
     }
 }
 
+static inline int cmp_vram(VGAState *s, int offset, int n)
+{
+    long *vp, *sp;
+
+    if (s->vram_shadow == NULL)
+        return 1;
+    vp = (long *)(s->vram_ptr + offset);
+    sp = (long *)(s->vram_shadow + offset);
+    while ((n -= sizeof(*vp)) >= 0) {
+        if (*vp++ != *sp++) {
+            memcpy(sp - 1, vp - 1, n + sizeof(*vp));
+            return 1;
+        }
+    }
+    return 0;
+}
+
+#ifdef USE_SSE2
+
+#include <signal.h>
+#include <setjmp.h>
+#include <emmintrin.h>
+
+int sse2_ok = 1;
+
+static inline unsigned int cpuid_edx(unsigned int op)
+{
+    unsigned int eax, edx;
+
+    __asm__("cpuid"
+            : "=a" (eax), "=d" (edx)
+            : "0" (op)
+            : "bx", "cx");
+
+    return edx;
+}
+
+jmp_buf sse_jbuf;
+
+void intr(int sig)
+{
+    sse2_ok = 0;
+    longjmp(sse_jbuf, 1);
+}
+
+void check_sse2(void)
+{
+    /* Check 1: What does CPUID say? */
+    if ((cpuid_edx(1) & 0x4000000) == 0) {
+        sse2_ok = 0;
+        return;
+    }
+
+    /* Check 2: Can we use SSE2 in anger? */
+    signal(SIGILL, intr);
+    if (setjmp(sse_jbuf) == 0)
+        __asm__("xorps %xmm0,%xmm0\n");
+}
+
+int vram_dirty(VGAState *s, int offset, int n)
+{
+    __m128i *sp, *vp;
+
+    if (s->vram_shadow == NULL)
+        return 1;
+    if (sse2_ok == 0)
+        return cmp_vram(s, offset, n);
+    vp = (__m128i *)(s->vram_ptr + offset);
+    sp = (__m128i *)(s->vram_shadow + offset);
+    while ((n -= sizeof(*vp)) >= 0) {
+        if (_mm_movemask_epi8(_mm_cmpeq_epi8(*sp, *vp)) != 0xffff) {
+            while (n >= 0) {
+                _mm_store_si128(sp++, _mm_load_si128(vp++));
+                n -= sizeof(*vp);
+            }
+            return 1;
+        }
+        sp++;
+        vp++;
+    }
+    return 0;
+}
+#else /* !USE_SSE2 */
+int vram_dirty(VGAState *s, int offset, int n)
+{
+    return cmp_vram(s, offset, n);
+}
+
+void check_sse2(void)
+{
+}
+#endif /* !USE_SSE2 */
+
 /* 
  * graphic modes
  */
@@ -1434,6 +1527,9 @@
     printf("w=%d h=%d v=%d line_offset=%d cr[0x09]=0x%02x cr[0x17]=0x%02x 
linecmp=%d sr[0x01]=0x%02x\n",
            width, height, v, line_offset, s->cr[9], s->cr[0x17], 
s->line_compare, s->sr[0x01]);
 #endif
+    for (y = 0; y < s->vram_size; y += TARGET_PAGE_SIZE)
+        if (vram_dirty(s, y, TARGET_PAGE_SIZE))
+            cpu_physical_memory_set_dirty(s->vram_offset + y);
     addr1 = (s->start_addr * 4);
     bwidth = width * 4;
     y_start = -1;
@@ -1536,8 +1632,17 @@
 
 void vga_update_display(void)
 {
+    static int loop;
     VGAState *s = vga_state;
     int full_update, graphic_mode;
+
+    /*
+     * Only update the display every other time.  The responsiveness is
+     * acceptable and it cuts down on the overhead of the VRAM compare
+     * in `vram_dirty'.
+     */
+    if (loop++ & 1)
+        return;
 
     if (s->ds->depth == 0) {
         /* nothing to do */
@@ -1569,7 +1674,6 @@
             full_update = 1;
         }
 
-        full_update = 1;
         switch(graphic_mode) {
         case GMODE_TEXT:
             vga_draw_text(s, full_update);
@@ -1874,7 +1978,13 @@
 #else
     s->vram_ptr = qemu_malloc(vga_ram_size);
 #endif
-
+    check_sse2();
+    s->vram_shadow = qemu_malloc(vga_ram_size+TARGET_PAGE_SIZE+1);
+    if (s->vram_shadow == NULL)
+        fprintf(stderr, "Cannot allocate %d bytes for VRAM shadow, "
+                "mouse will be slow\n", vga_ram_size);
+    s->vram_shadow = (uint8_t *)((long)(s->vram_shadow + TARGET_PAGE_SIZE - 1)
+                                 & ~(TARGET_PAGE_SIZE - 1));
     s->vram_offset = vga_ram_offset;
     s->vram_size = vga_ram_size;
     s->ds = ds;
diff -r e04978011d2d -r 25003dd43a92 tools/ioemu/hw/vga_int.h
--- a/tools/ioemu/hw/vga_int.h  Fri Mar 17 21:26:24 2006
+++ b/tools/ioemu/hw/vga_int.h  Fri Mar 17 22:37:28 2006
@@ -76,6 +76,7 @@
 
 #define VGA_STATE_COMMON                                                \
     uint8_t *vram_ptr;                                                  \
+    uint8_t *vram_shadow;                                               \
     unsigned long vram_offset;                                          \
     unsigned int vram_size;                                             \
     uint32_t latch;                                                     \
diff -r e04978011d2d -r 25003dd43a92 tools/ioemu/sdl.c
--- a/tools/ioemu/sdl.c Fri Mar 17 21:26:24 2006
+++ b/tools/ioemu/sdl.c Fri Mar 17 22:37:28 2006
@@ -405,7 +405,7 @@
     if (state & SDL_BUTTON(SDL_BUTTON_WHEELDOWN))
         dz++;
 #endif
-    kbd_mouse_event(dx, dy, dz, buttons);
+    kbd_mouse_event(dx, dy, dz, buttons, 0, 0);
 }
 
 static void toggle_full_screen(DisplayState *ds)
diff -r e04978011d2d -r 25003dd43a92 tools/ioemu/target-i386-dm/Makefile
--- a/tools/ioemu/target-i386-dm/Makefile       Fri Mar 17 21:26:24 2006
+++ b/tools/ioemu/target-i386-dm/Makefile       Fri Mar 17 22:37:28 2006
@@ -13,8 +13,15 @@
 VPATH+=:$(SRC_PATH)/linux-user
 DEFINES+=-I$(SRC_PATH)/linux-user -I$(SRC_PATH)/linux-user/$(TARGET_ARCH)
 endif
-CFLAGS+=-g -fno-strict-aliasing
-LDFLAGS=-g
+
+SSE2 := $(call test-gcc-flag,$(CC),-msse2)
+ifeq ($(SSE2),-msse2)
+CFLAGS += -DUSE_SSE2=1 -msse2
+endif
+
+CFLAGS += -g -fno-strict-aliasing $(LOCAL_CFLAGS)
+LDFLAGS = -g
+
 LIBS=
 HELPER_CFLAGS=$(CFLAGS)
 DYNGEN=../dyngen$(EXESUF)
diff -r e04978011d2d -r 25003dd43a92 tools/ioemu/target-i386-dm/helper2.c
--- a/tools/ioemu/target-i386-dm/helper2.c      Fri Mar 17 21:26:24 2006
+++ b/tools/ioemu/target-i386-dm/helper2.c      Fri Mar 17 22:37:28 2006
@@ -447,9 +447,9 @@
             }
         }
 
-        /* Wait up to one seconds. */
+        /* Wait up to 10 msec. */
         tv.tv_sec = 0;
-        tv.tv_usec = 100000;
+        tv.tv_usec = 10000;
 
         retval = select(highest_fds+1, &wakeup_rfds, NULL, NULL, &tv);
         if (retval == -1) {
diff -r e04978011d2d -r 25003dd43a92 tools/ioemu/vl.c
--- a/tools/ioemu/vl.c  Fri Mar 17 21:26:24 2006
+++ b/tools/ioemu/vl.c  Fri Mar 17 22:37:28 2006
@@ -464,11 +464,11 @@
     }
 }
 
-void kbd_mouse_event(int dx, int dy, int dz, int buttons_state)
+void kbd_mouse_event(int dx, int dy, int dz, int buttons_state, int x, int y)
 {
     if (qemu_put_mouse_event) {
         qemu_put_mouse_event(qemu_put_mouse_event_opaque,
-                             dx, dy, dz, buttons_state);
+                             dx, dy, dz, buttons_state, x, y);
     }
 }
 
diff -r e04978011d2d -r 25003dd43a92 tools/ioemu/vl.h
--- a/tools/ioemu/vl.h  Fri Mar 17 21:26:24 2006
+++ b/tools/ioemu/vl.h  Fri Mar 17 22:37:28 2006
@@ -139,13 +139,13 @@
 #define MOUSE_EVENT_MBUTTON 0x04
 
 typedef void QEMUPutKBDEvent(void *opaque, int keycode);
-typedef void QEMUPutMouseEvent(void *opaque, int dx, int dy, int dz, int 
buttons_state);
+typedef void QEMUPutMouseEvent(void *opaque, int dx, int dy, int dz, int 
buttons_state, int x, int y);
 
 void qemu_add_kbd_event_handler(QEMUPutKBDEvent *func, void *opaque);
 void qemu_add_mouse_event_handler(QEMUPutMouseEvent *func, void *opaque);
 
 void kbd_put_keycode(int keycode);
-void kbd_mouse_event(int dx, int dy, int dz, int buttons_state);
+void kbd_mouse_event(int dx, int dy, int dz, int buttons_state, int x, int y);
 
 /* keysym is a unicode code except for special keys (see QEMU_KEY_xxx
    constants) */
@@ -618,6 +618,12 @@
 extern const char* keyboard_layout;
 extern int repeat_key;
 
+/* Mice */
+
+void summa_init(void *cookie, CharDriverState *chr);
+
+extern int summa_ok;
+
 /* mc146818rtc.c */
 
 typedef struct RTCState RTCState;
@@ -630,6 +636,7 @@
 
 typedef struct SerialState SerialState;
 SerialState *serial_init(int base, int irq, CharDriverState *chr);
+void ser_queue(SerialState *s, unsigned char c);
 
 /* i8259.c */
 
diff -r e04978011d2d -r 25003dd43a92 tools/ioemu/vnc.c
--- a/tools/ioemu/vnc.c Fri Mar 17 21:26:24 2006
+++ b/tools/ioemu/vnc.c Fri Mar 17 22:37:28 2006
@@ -46,8 +46,9 @@
 #endif
 
 static rfbScreenInfoPtr screen;
-static DisplayState* ds_sdl=0;
-static void* kbd_layout=0; // TODO: move into rfbClient
+static DisplayState* ds_sdl;
+static void* kbd_layout; // TODO: move into rfbClient
+static int ctl_keys; // Ctrl+Alt starts calibration
 
 /* mouse stuff */
 
@@ -123,12 +124,15 @@
 static rectangle_t last_update, before_update;
 static int updates_since_mouse=0;
 
+extern int mouse_maxx, mouse_maxy;
 static int mouse_x,mouse_y;
 static int new_mouse_x,new_mouse_y,new_mouse_z,new_mouse_buttons;
 
-static void init_mouse(int initial_x,int initial_y) {
-       mouse_x=new_mouse_x=initial_x;
-       mouse_y=new_mouse_y=initial_y;
+static void init_mouse(int max_x,int max_y) {
+       mouse_maxx=max_x - 1;
+       mouse_maxy=max_y - 1;
+       mouse_x=new_mouse_x=max_x/2;
+       mouse_y=new_mouse_y=max_y/2;
        new_mouse_z=new_mouse_buttons=0;
        mouse_magic->calibration = 0;
 }
@@ -137,6 +141,15 @@
        int dx=0,dy=0,dz=new_mouse_z;
        static int counter=1;
 
+       /*
+        *  Simulate lifting the mouse by pressing left <ctl><alt> together
+        *  e.g. don't send mouse events.
+        */
+       if (ctl_keys == 3) {
+               mouse_x = new_mouse_x;
+               mouse_y = new_mouse_y;
+               return;
+       }
        counter++;
        if(!mouse_magic->calibration && counter>=2) { counter=0; return; }
 
@@ -153,7 +166,7 @@
                }
        }
        //fprintf(stderr,"sending mouse event %d,%d\n",dx,dy);
-       kbd_mouse_event(dx,dy,dz,new_mouse_buttons);
+       kbd_mouse_event(dx,dy,dz,new_mouse_buttons,new_mouse_x,new_mouse_y);
        mouse_x+=dx;
        mouse_y+=dy;
                
@@ -237,7 +250,7 @@
        
        if(calibration_step==0) {
                x=0; y=1;
-               kbd_mouse_event(0,-1,0,0);
+               kbd_mouse_event(0,-1,0,0,x,y);
                calibration_step++;
        } else if(calibration_step==1) {
                // find out the initial position of the cursor
@@ -269,7 +282,7 @@
                } else {
                        y++;
 move_calibrate:
-                       kbd_mouse_event(-x,-y,0,0);
+                       kbd_mouse_event(-x,-y,0,0,x,y);
                        before_update=last_update;
                }
        } else if(calibration_step==3) {
@@ -375,12 +388,11 @@
                fprintf(stderr,"Warning: mouse calibration interrupted by video 
mode change\n");
                stop_mouse_calibration();
        }
-       init_mouse(w/2,h/2);
+       init_mouse(w,h);
 }
 
 static void vnc_process_key(rfbBool down, rfbKeySym keySym, rfbClientPtr cl)
 {
-       static int magic=0; // Ctrl+Alt starts calibration
 
        if(is_active_console(vga_console)) {
                WORD keycode=keysym2scancode(kbd_layout, keySym);
@@ -416,24 +428,28 @@
        }
        if(down) {
                if(keySym==XK_Control_L)
-                       magic|=1;
+                       ctl_keys|=1;
                else if(keySym==XK_Alt_L)
-                       magic|=2;
+                       ctl_keys|=2;
        } else {
-               if((magic&3)==3) {
+               if (keySym == XK_Control_L)
+                       ctl_keys &= ~1;
+               else if (keySym == XK_Alt_L)
+                       ctl_keys &= ~2;
+               if((ctl_keys&3)==3) {
                        switch(keySym) {
                                case XK_Control_L:
-                                       magic&=~1;
+                                       ctl_keys&=~1;
                                        break;
                                case XK_Alt_L:
-                                       magic&=~2;
+                                       ctl_keys&=~2;
                                        break;
                                case XK_m:
-                                       magic=0;
+                                       ctl_keys=0;
                                        start_mouse_calibration();
                                        break;
                                case XK_1 ... XK_9:
-                                       magic=0;
+                                       ctl_keys=0;
                                        fprintf(stderr,"switch to 
%d\n",keySym-XK_1);
                                        console_select(keySym - XK_1);
                                        if (is_active_console(vga_console)) {
@@ -483,7 +499,8 @@
     char  host[1024];
     char *p;
     rfbClientPtr cl;
-    
+
+       summa_ok = 1;
        if(!keyboard_layout) {
                fprintf(stderr, "No keyboard language specified\n");
                exit(1);
@@ -513,6 +530,10 @@
        screen->serverFormat.redMax = 31;
        screen->serverFormat.greenMax = 63;
        screen->serverFormat.blueMax = 31;
+
+#ifdef VNC_EAGER_EVENTS
+       screen->handleEventsEagerly = TRUE;
+#endif // VNC_EAGER_EVENTS
 
     if (port != 0) 
         screen->port = port;
diff -r e04978011d2d -r 25003dd43a92 tools/libxc/xg_private.c
--- a/tools/libxc/xg_private.c  Fri Mar 17 21:26:24 2006
+++ b/tools/libxc/xg_private.c  Fri Mar 17 22:37:28 2006
@@ -77,10 +77,11 @@
         return (char *)in_buf;
     }
 
-    out_len = in_buf[in_size-4] +
-        (256 * (in_buf[in_size-3] +
-                (256 * (in_buf[in_size-2] +
-                        (256 * in_buf[in_size-1])))));
+    out_len = (unsigned char)in_buf[in_size-4] +
+        (256 * ((unsigned char)in_buf[in_size-3] +
+                (256 * ((unsigned char)in_buf[in_size-2] +
+                        (256 * (unsigned char)in_buf[in_size-1])))));
+
     bzero(&zStream, sizeof(zStream));
     out_buf = malloc(out_len + 16);        /* Leave a little extra space */
     if ( out_buf == NULL )
diff -r e04978011d2d -r 25003dd43a92 tools/xenstore/xenstored_core.c
--- a/tools/xenstore/xenstored_core.c   Fri Mar 17 21:26:24 2006
+++ b/tools/xenstore/xenstored_core.c   Fri Mar 17 22:37:28 2006
@@ -1113,6 +1113,34 @@
        send_ack(conn, XS_SET_PERMS);
 }
 
+static void do_debug(struct connection *conn, struct buffered_data *in)
+{
+       int num;
+
+       num = xs_count_strings(in->buffer, in->used);
+
+       if (streq(in->buffer, "print")) {
+               if (num < 2) {
+                       send_error(conn, EINVAL);
+                       return;
+               }
+               xprintf("debug: %s", in->buffer + get_string(in, 0));
+       }
+       if (streq(in->buffer, "check"))
+               check_store();
+#ifdef TESTING
+       /* For testing, we allow them to set id. */
+       if (streq(in->buffer, "setid")) {
+               conn->id = atoi(in->buffer + get_string(in, 0));
+       } else if (streq(in->buffer, "failtest")) {
+               if (get_string(in, 0) < in->used)
+                       srandom(atoi(in->buffer + get_string(in, 0)));
+               failtest = true;
+       }
+#endif /* TESTING */
+       send_ack(conn, XS_DEBUG);
+}
+
 /* Process "in" for conn: "in" will vanish after this conversation, so
  * we can talloc off it for temporary variables.  May free "conn".
  */
@@ -1159,21 +1187,7 @@
                break;
 
        case XS_DEBUG:
-               if (streq(in->buffer, "print"))
-                       xprintf("debug: %s", in->buffer + get_string(in, 0));
-               if (streq(in->buffer, "check"))
-                       check_store();
-#ifdef TESTING
-               /* For testing, we allow them to set id. */
-               if (streq(in->buffer, "setid")) {
-                       conn->id = atoi(in->buffer + get_string(in, 0));
-               } else if (streq(in->buffer, "failtest")) {
-                       if (get_string(in, 0) < in->used)
-                               srandom(atoi(in->buffer + get_string(in, 0)));
-                       failtest = true;
-               }
-#endif /* TESTING */
-               send_ack(conn, XS_DEBUG);
+               do_debug(conn, in);
                break;
 
        case XS_WATCH:
diff -r e04978011d2d -r 25003dd43a92 xen/arch/ia64/xen/xentime.c
--- a/xen/arch/ia64/xen/xentime.c       Fri Mar 17 21:26:24 2006
+++ b/xen/arch/ia64/xen/xentime.c       Fri Mar 17 22:37:28 2006
@@ -265,4 +265,8 @@
        return 1;
 }
 
-
+void send_timer_event(struct vcpu *v)
+{
+       send_guest_virq(v, VIRQ_TIMER);
+}
+
diff -r e04978011d2d -r 25003dd43a92 xen/arch/x86/domain.c
--- a/xen/arch/x86/domain.c     Fri Mar 17 21:26:24 2006
+++ b/xen/arch/x86/domain.c     Fri Mar 17 22:37:28 2006
@@ -1030,10 +1030,10 @@
 
             v->arch.guest_table_user = mk_pagetable(0);
         }
-
-        if ( hvm_guest(v) )
-            hvm_relinquish_guest_resources(v);
-    }
+    }
+
+    if ( hvm_guest(d->vcpu[0]) )
+        hvm_relinquish_guest_resources(d);
 
     shadow_mode_disable(d);
 
diff -r e04978011d2d -r 25003dd43a92 xen/arch/x86/hvm/svm/svm.c
--- a/xen/arch/x86/hvm/svm/svm.c        Fri Mar 17 21:26:24 2006
+++ b/xen/arch/x86/hvm/svm/svm.c        Fri Mar 17 22:37:28 2006
@@ -77,6 +77,8 @@
         int vector, int has_code);
 void svm_dump_regs(const char *from, struct cpu_user_regs *regs);
 
+static void svm_relinquish_guest_resources(struct domain *d);
+
 static struct asid_pool ASIDpool[NR_CPUS];
 
 /*
@@ -195,12 +197,6 @@
 int svm_initialize_guest_resources(struct vcpu *v)
 {
     svm_final_setup_guest(v);
-    return 1;
-}
-
-int svm_relinquish_guest_resources(struct vcpu *v)
-{
-    svm_relinquish_resources(v);
     return 1;
 }
 
@@ -722,43 +718,35 @@
 }
 
 
-void svm_relinquish_resources(struct vcpu *v)
-{
-    struct hvm_virpit *vpit;
+static void svm_relinquish_guest_resources(struct domain *d)
+{
     extern void destroy_vmcb(struct arch_svm_struct *); /* XXX */
-
+    struct vcpu *v;
+
+    for_each_vcpu ( d, v )
+    {
 #if 0
-    /* 
-     * This is not stored at the moment. We need to keep it somewhere and free
-     * it Or maybe not, as it's a per-cpu-core item, and I guess we don't
-     * normally remove CPU's other than for hot-plug capable systems, where I
-     * guess we have to allocate and free host-save area in this case. Let's
-     * not worry about it at the moment, as loosing one page per CPU hot-plug
-     * event doesn't seem that excessive. But I may be wrong.
-     */
-    free_host_save_area(v->arch.hvm_svm.host_save_area);
-#endif
-
-    if ( v->vcpu_id == 0 )
-    {
-        /* unmap IO shared page */
-        struct domain *d = v->domain;
-        if ( d->arch.hvm_domain.shared_page_va )
-            unmap_domain_page_global(
-                (void *)d->arch.hvm_domain.shared_page_va);
-        shadow_direct_map_clean(d);
-    }
-
-    destroy_vmcb(&v->arch.hvm_svm);
-    free_monitor_pagetable(v);
-    vpit = &v->domain->arch.hvm_domain.vpit;
-    kill_timer(&vpit->pit_timer);
-    kill_timer(&v->arch.hvm_svm.hlt_timer);
-    if ( hvm_apic_support(v->domain) && (VLAPIC(v) != NULL) ) 
-    {
-        kill_timer( &(VLAPIC(v)->vlapic_timer) );
-        xfree( VLAPIC(v) );
-    }
+        /* Memory leak by not freeing this. XXXKAF: *Why* is not per core?? */
+        free_host_save_area(v->arch.hvm_svm.host_save_area);
+#endif
+
+        destroy_vmcb(&v->arch.hvm_svm);
+        free_monitor_pagetable(v);
+        kill_timer(&v->arch.hvm_svm.hlt_timer);
+        if ( hvm_apic_support(v->domain) && (VLAPIC(v) != NULL) ) 
+        {
+            kill_timer( &(VLAPIC(v)->vlapic_timer) );
+            xfree(VLAPIC(v));
+        }
+    }
+
+    kill_timer(&d->arch.hvm_domain.vpit.pit_timer);
+
+    if ( d->arch.hvm_domain.shared_page_va )
+        unmap_domain_page_global(
+            (void *)d->arch.hvm_domain.shared_page_va);
+
+    shadow_direct_map_clean(d);
 }
 
 
diff -r e04978011d2d -r 25003dd43a92 xen/arch/x86/hvm/vmx/vmx.c
--- a/xen/arch/x86/hvm/vmx/vmx.c        Fri Mar 17 21:26:24 2006
+++ b/xen/arch/x86/hvm/vmx/vmx.c        Fri Mar 17 22:37:28 2006
@@ -78,30 +78,30 @@
     }
 }
 
-void vmx_relinquish_resources(struct vcpu *v)
-{
-    struct hvm_virpit *vpit;
-
-    if (v->vcpu_id == 0) {
-        /* unmap IO shared page */
-        struct domain *d = v->domain;
-        if ( d->arch.hvm_domain.shared_page_va )
-            unmap_domain_page_global(
+static void vmx_relinquish_guest_resources(struct domain *d)
+{
+    struct vcpu *v;
+
+    for_each_vcpu ( d, v )
+    {
+        vmx_request_clear_vmcs(v);
+        destroy_vmcs(&v->arch.hvm_vmx);
+        free_monitor_pagetable(v);
+        kill_timer(&v->arch.hvm_vmx.hlt_timer);
+        if ( hvm_apic_support(v->domain) && (VLAPIC(v) != NULL) )
+        {
+            kill_timer(&VLAPIC(v)->vlapic_timer);
+            xfree(VLAPIC(v));
+        }
+    }
+
+    kill_timer(&d->arch.hvm_domain.vpit.pit_timer);
+
+    if ( d->arch.hvm_domain.shared_page_va )
+        unmap_domain_page_global(
                (void *)d->arch.hvm_domain.shared_page_va);
-        shadow_direct_map_clean(d);
-    }
-
-    vmx_request_clear_vmcs(v);
-    destroy_vmcs(&v->arch.hvm_vmx);
-    free_monitor_pagetable(v);
-    vpit = &v->domain->arch.hvm_domain.vpit;
-    kill_timer(&vpit->pit_timer);
-    kill_timer(&v->arch.hvm_vmx.hlt_timer);
-    if ( hvm_apic_support(v->domain) && (VLAPIC(v) != NULL) )
-    {
-        kill_timer(&VLAPIC(v)->vlapic_timer);
-        xfree(VLAPIC(v));
-    }
+
+    shadow_direct_map_clean(d);
 }
 
 #ifdef __x86_64__
@@ -231,10 +231,9 @@
         if ((msr_content & EFER_LME) ^
             test_bit(VMX_CPU_STATE_LME_ENABLED,
                      &vc->arch.hvm_vmx.cpu_state)){
-            if (test_bit(VMX_CPU_STATE_PG_ENABLED,
-                         &vc->arch.hvm_vmx.cpu_state) ||
-                !test_bit(VMX_CPU_STATE_PAE_ENABLED,
-                          &vc->arch.hvm_vmx.cpu_state)){
+            if ( vmx_paging_enabled(vc) ||
+                 !test_bit(VMX_CPU_STATE_PAE_ENABLED,
+                           &vc->arch.hvm_vmx.cpu_state)) {
                 vmx_inject_exception(vc, TRAP_gp_fault, 0);
             }
         }
@@ -324,12 +323,6 @@
 int vmx_initialize_guest_resources(struct vcpu *v)
 {
     vmx_final_setup_guest(v);
-    return 1;
-}
-
-int vmx_relinquish_guest_resources(struct vcpu *v)
-{
-    vmx_relinquish_resources(v);
     return 1;
 }
 
@@ -677,27 +670,31 @@
 /* Reserved bits: [31:15], [12:11], [9], [6], [2:1] */
 #define VMX_VCPU_CPUID_L1_RESERVED 0xffff9a46
 
-static void vmx_vmexit_do_cpuid(unsigned long input, struct cpu_user_regs 
*regs)
-{
+static void vmx_vmexit_do_cpuid(struct cpu_user_regs *regs)
+{
+    unsigned int input = (unsigned int)regs->eax;
+    unsigned int count = (unsigned int)regs->ecx;
     unsigned int eax, ebx, ecx, edx;
     unsigned long eip;
     struct vcpu *v = current;
 
     __vmread(GUEST_RIP, &eip);
 
-    HVM_DBG_LOG(DBG_LEVEL_1,
-                "do_cpuid: (eax) %lx, (ebx) %lx, (ecx) %lx, (edx) %lx,"
-                " (esi) %lx, (edi) %lx",
+    HVM_DBG_LOG(DBG_LEVEL_3, "(eax) 0x%08lx, (ebx) 0x%08lx, "
+                "(ecx) 0x%08lx, (edx) 0x%08lx, (esi) 0x%08lx, (edi) 0x%08lx",
                 (unsigned long)regs->eax, (unsigned long)regs->ebx,
                 (unsigned long)regs->ecx, (unsigned long)regs->edx,
                 (unsigned long)regs->esi, (unsigned long)regs->edi);
 
-    cpuid(input, &eax, &ebx, &ecx, &edx);
+    if ( input == 4 )
+        cpuid_count(input, count, &eax, &ebx, &ecx, &edx);
+    else
+        cpuid(input, &eax, &ebx, &ecx, &edx);
 
     if ( input == 1 )
     {
         if ( hvm_apic_support(v->domain) &&
-                !vlapic_global_enabled((VLAPIC(v))) )
+             !vlapic_global_enabled((VLAPIC(v))) )
             clear_bit(X86_FEATURE_APIC, &edx);
 
 #if CONFIG_PAGING_LEVELS < 3
@@ -732,10 +729,12 @@
     regs->ecx = (unsigned long) ecx;
     regs->edx = (unsigned long) edx;
 
-    HVM_DBG_LOG(DBG_LEVEL_1,
-                "vmx_vmexit_do_cpuid: eip: %lx, input: %lx, out:eax=%x, 
ebx=%x, ecx=%x, edx=%x",
-                eip, input, eax, ebx, ecx, edx);
-
+    HVM_DBG_LOG(DBG_LEVEL_3, "eip@%lx, input: 0x%lx, "
+                "output: eax = 0x%08lx, ebx = 0x%08lx, "
+                "ecx = 0x%08lx, edx = 0x%08lx",
+                (unsigned long)eip, (unsigned long)input,
+                (unsigned long)eax, (unsigned long)ebx,
+                (unsigned long)ecx, (unsigned long)edx);
 }
 
 #define CASE_GET_REG_P(REG, reg)    \
@@ -1220,8 +1219,6 @@
 
     if ( (value & X86_CR0_PE) && (value & X86_CR0_PG) && !paging_enabled )
     {
-        unsigned long cr4;
-
         /*
          * Trying to enable guest paging.
          * The guest CR3 must be pointing to the guest physical.
@@ -1270,16 +1267,6 @@
                 domain_crash_synchronous(); /* need to take a clean path */
             }
 #endif
-        }
-
-        /* update CR4's PAE if needed */
-        __vmread(GUEST_CR4, &cr4);
-        if ( (!(cr4 & X86_CR4_PAE)) &&
-             test_bit(VMX_CPU_STATE_PAE_ENABLED,
-                      &v->arch.hvm_vmx.cpu_state) )
-        {
-            HVM_DBG_LOG(DBG_LEVEL_1, "enable PAE in cr4\n");
-            __vmwrite(GUEST_CR4, cr4 | X86_CR4_PAE);
         }
 
         /*
@@ -2033,8 +2020,8 @@
         __hvm_bug(&regs);
         break;
     case EXIT_REASON_CPUID:
+        vmx_vmexit_do_cpuid(&regs);
         __get_instruction_length(inst_len);
-        vmx_vmexit_do_cpuid(regs.eax, &regs);
         __update_guest_eip(inst_len);
         break;
     case EXIT_REASON_HLT:
diff -r e04978011d2d -r 25003dd43a92 xen/arch/x86/hvm/vmx/x86_32/exits.S
--- a/xen/arch/x86/hvm/vmx/x86_32/exits.S       Fri Mar 17 21:26:24 2006
+++ b/xen/arch/x86/hvm/vmx/x86_32/exits.S       Fri Mar 17 22:37:28 2006
@@ -89,7 +89,7 @@
         call vmx_vmexit_handler
         jmp vmx_asm_do_resume
 
-.macro vmx_asm_common launch initialized
+.macro vmx_asm_common launch, initialized
 1:
 /* vmx_test_all_events */
         .if \initialized
@@ -140,10 +140,10 @@
 .endm
 
 ENTRY(vmx_asm_do_launch)
-    vmx_asm_common 1 0
+    vmx_asm_common 1, 0
 
 ENTRY(vmx_asm_do_resume)
-    vmx_asm_common 0 1
+    vmx_asm_common 0, 1
 
 ENTRY(vmx_asm_do_relaunch)
-    vmx_asm_common 1 1
+    vmx_asm_common 1, 1
diff -r e04978011d2d -r 25003dd43a92 xen/arch/x86/hvm/vmx/x86_64/exits.S
--- a/xen/arch/x86/hvm/vmx/x86_64/exits.S       Fri Mar 17 21:26:24 2006
+++ b/xen/arch/x86/hvm/vmx/x86_64/exits.S       Fri Mar 17 22:37:28 2006
@@ -97,7 +97,7 @@
         call vmx_vmexit_handler
         jmp vmx_asm_do_resume
 
-.macro vmx_asm_common launch initialized 
+.macro vmx_asm_common launch, initialized 
 1:
         .if \initialized
 /* vmx_test_all_events */
@@ -147,10 +147,10 @@
 .endm
 
 ENTRY(vmx_asm_do_launch)
-      vmx_asm_common 1 0
+      vmx_asm_common 1, 0
 
 ENTRY(vmx_asm_do_resume)
-      vmx_asm_common 0 1
+      vmx_asm_common 0, 1
 
 ENTRY(vmx_asm_do_relaunch)
-      vmx_asm_common 1 1
+      vmx_asm_common 1, 1
diff -r e04978011d2d -r 25003dd43a92 xen/arch/x86/time.c
--- a/xen/arch/x86/time.c       Fri Mar 17 21:26:24 2006
+++ b/xen/arch/x86/time.c       Fri Mar 17 22:37:28 2006
@@ -923,6 +923,11 @@
     setup_irq(0, &irq0);
 }
 
+void send_timer_event(struct vcpu *v)
+{
+    send_guest_virq(v, VIRQ_TIMER);
+}
+
 /*
  * Local variables:
  * mode: C
diff -r e04978011d2d -r 25003dd43a92 xen/common/sched_sedf.c
--- a/xen/common/sched_sedf.c   Fri Mar 17 21:26:24 2006
+++ b/xen/common/sched_sedf.c   Fri Mar 17 22:37:28 2006
@@ -57,11 +57,9 @@
 #define WEIGHT_PERIOD (MILLISECS(100))
 #define WEIGHT_SAFETY (MILLISECS(5))
 
-/* FIXME: need to validate that these are sane */
-#define PERIOD_MAX ULONG_MAX
-#define PERIOD_MIN (MICROSECS(10))
-#define SLICE_MAX ULONG_MAX
-#define SLICE_MIN (MICROSECS(5))
+#define PERIOD_MAX MILLISECS(10000) /* 10s  */
+#define PERIOD_MIN (MICROSECS(10))  /* 10us */
+#define SLICE_MIN (MICROSECS(5))    /*  5us */
 
 #define IMPLY(a, b) (!(a) || (b))
 #define EQ(a, b) ((!!(a)) == (!!(b)))
@@ -1617,9 +1615,8 @@
                  */
                 if ( (cmd->u.sedf.period > PERIOD_MAX) ||
                      (cmd->u.sedf.period < PERIOD_MIN) ||
-                     (cmd->u.sedf.slice  > SLICE_MAX)  ||
-                     (cmd->u.sedf.slice  < SLICE_MIN)  ||
-                     (cmd->u.sedf.slice > cmd->u.sedf.period) )
+                     (cmd->u.sedf.slice  > cmd->u.sedf.period) ||
+                     (cmd->u.sedf.slice  < SLICE_MIN) )
                     return -EINVAL;
                 EDOM_INFO(v)->weight = 0;
                 EDOM_INFO(v)->extraweight = 0;
diff -r e04978011d2d -r 25003dd43a92 xen/common/schedule.c
--- a/xen/common/schedule.c     Fri Mar 17 21:26:24 2006
+++ b/xen/common/schedule.c     Fri Mar 17 22:37:28 2006
@@ -574,7 +574,7 @@
     {
         update_dom_time(next);
         if ( next->sleep_tick != schedule_data[cpu].tick )
-            send_guest_virq(next, VIRQ_TIMER);
+            send_timer_event(next);
     }
 
     TRACE_4D(TRC_SCHED_SWITCH,
@@ -610,7 +610,7 @@
     if ( !is_idle_vcpu(v) )
     {
         update_dom_time(v);
-        send_guest_virq(v, VIRQ_TIMER);
+        send_timer_event(v);
     }
 
     page_scrub_schedule_work();
@@ -624,7 +624,7 @@
     struct vcpu *v = data;
 
     update_dom_time(v);
-    send_guest_virq(v, VIRQ_TIMER);
+    send_timer_event(v);
 }
 
 /* SCHEDOP_poll timeout callback. */
diff -r e04978011d2d -r 25003dd43a92 xen/drivers/char/console.c
--- a/xen/drivers/char/console.c        Fri Mar 17 21:26:24 2006
+++ b/xen/drivers/char/console.c        Fri Mar 17 22:37:28 2006
@@ -683,8 +683,6 @@
     (void)vsnprintf(buf, sizeof(buf), fmt, args);
     va_end(args);
 
-    debugger_trap_immediate();
-
     /* Spit out multiline message in one go. */
     spin_lock_irqsave(&lock, flags);
     printk("\n****************************************\n");
@@ -693,6 +691,8 @@
     printk("****************************************\n\n");
     printk("Reboot in five seconds...\n");
     spin_unlock_irqrestore(&lock, flags);
+
+    debugger_trap_immediate();
 
     watchdog_disable();
     mdelay(5000);
diff -r e04978011d2d -r 25003dd43a92 xen/include/asm-x86/hvm/hvm.h
--- a/xen/include/asm-x86/hvm/hvm.h     Fri Mar 17 21:26:24 2006
+++ b/xen/include/asm-x86/hvm/hvm.h     Fri Mar 17 22:37:28 2006
@@ -35,8 +35,8 @@
     /*
      * Initialize/relinguish HVM guest resources
      */
-    int (*initialize_guest_resources)(struct vcpu *v);
-    int (*relinquish_guest_resources)(struct vcpu *v);
+    int  (*initialize_guest_resources)(struct vcpu *v);
+    void (*relinquish_guest_resources)(struct domain *d);
 
     /*
      * Store and load guest state:
@@ -80,24 +80,23 @@
 static inline void
 hvm_disable(void)
 {
-    if (hvm_funcs.disable)
-       hvm_funcs.disable();
+    if ( hvm_funcs.disable )
+        hvm_funcs.disable();
 }
 
 static inline int
 hvm_initialize_guest_resources(struct vcpu *v)
 {
-    if (hvm_funcs.initialize_guest_resources)
-       return hvm_funcs.initialize_guest_resources(v);
+    if ( hvm_funcs.initialize_guest_resources )
+        return hvm_funcs.initialize_guest_resources(v);
     return 0;
 }
 
-static inline int
-hvm_relinquish_guest_resources(struct vcpu *v)
+static inline void
+hvm_relinquish_guest_resources(struct domain *d)
 {
     if (hvm_funcs.relinquish_guest_resources)
-       return hvm_funcs.relinquish_guest_resources(v);
-    return 0;
+        hvm_funcs.relinquish_guest_resources(d);
 }
 
 static inline void
@@ -134,9 +133,9 @@
         hvm_funcs.restore_msrs(v);
 }
 #else
-#define        hvm_save_segments(v)    ((void)0)
-#define        hvm_load_msrs(v)        ((void)0)
-#define        hvm_restore_msrs(v)     ((void)0)
+#define hvm_save_segments(v)    ((void)0)
+#define hvm_load_msrs(v)        ((void)0)
+#define hvm_restore_msrs(v)     ((void)0)
 #endif /* __x86_64__ */
 
 static inline void
diff -r e04978011d2d -r 25003dd43a92 xen/include/asm-x86/hvm/svm/svm.h
--- a/xen/include/asm-x86/hvm/svm/svm.h Fri Mar 17 21:26:24 2006
+++ b/xen/include/asm-x86/hvm/svm/svm.h Fri Mar 17 22:37:28 2006
@@ -44,7 +44,6 @@
 extern void svm_vmwrite(struct vcpu *v, int index, unsigned long value);
 extern void svm_final_setup_guest(struct vcpu *v); 
 extern int svm_paging_enabled(struct vcpu *v); 
-extern void svm_relinquish_resources(struct vcpu *v);
 extern void svm_dump_vmcb(const char *from, struct vmcb_struct *vmcb);
 extern void svm_stts(struct vcpu *v); 
 extern void svm_do_launch(struct vcpu *v);
diff -r e04978011d2d -r 25003dd43a92 xen/include/asm-x86/hvm/vmx/vmcs.h
--- a/xen/include/asm-x86/hvm/vmx/vmcs.h        Fri Mar 17 21:26:24 2006
+++ b/xen/include/asm-x86/hvm/vmx/vmcs.h        Fri Mar 17 22:37:28 2006
@@ -28,13 +28,11 @@
 extern void stop_vmx(void);
 
 void vmx_final_setup_guest(struct vcpu *v);
-void vmx_relinquish_resources(struct vcpu *v);
 
 void vmx_enter_scheduler(void);
 
 enum {
-    VMX_CPU_STATE_PG_ENABLED=0,
-    VMX_CPU_STATE_PAE_ENABLED,
+    VMX_CPU_STATE_PAE_ENABLED=0,
     VMX_CPU_STATE_LME_ENABLED,
     VMX_CPU_STATE_LMA_ENABLED,
     VMX_CPU_STATE_ASSIST_ENABLED,
diff -r e04978011d2d -r 25003dd43a92 xen/include/asm-x86/mm.h
--- a/xen/include/asm-x86/mm.h  Fri Mar 17 21:26:24 2006
+++ b/xen/include/asm-x86/mm.h  Fri Mar 17 22:37:28 2006
@@ -100,7 +100,7 @@
 
 #ifdef __x86_64__
 #define PGT_high_mfn_shift  52
-#define PGT_high_mfn_mask   (0x7ffUL << PGT_high_mfn_shift)
+#define PGT_high_mfn_mask   (0xfffUL << PGT_high_mfn_shift)
 #define PGT_mfn_mask        (((1U<<23)-1) | PGT_high_mfn_mask)
 #define PGT_high_mfn_nx     (0x800UL << PGT_high_mfn_shift)
 #else
@@ -363,8 +363,8 @@
 
 #ifdef PERF_ARRAYS
 
-void ptwr_eip_stat_reset();
-void ptwr_eip_stat_print();
+void ptwr_eip_stat_reset(void);
+void ptwr_eip_stat_print(void);
 
 #else
 
diff -r e04978011d2d -r 25003dd43a92 xen/include/public/sched.h
--- a/xen/include/public/sched.h        Fri Mar 17 21:26:24 2006
+++ b/xen/include/public/sched.h        Fri Mar 17 22:37:28 2006
@@ -12,24 +12,18 @@
 #include "event_channel.h"
 
 /*
- * There are two forms of this hypercall.
- * 
- * The first and preferred version is only available from Xen 3.0.2. 
  * The prototype for this hypercall is:
  *  long sched_op_new(int cmd, void *arg)
  * @cmd == SCHEDOP_??? (scheduler operation).
  * @arg == Operation-specific extra argument(s), as described below.
  * 
- * The legacy version of this hypercall supports only the following commands:
- * SCHEDOP_yield, SCHEDOP_block, and SCHEDOP_shutdown. The prototype for the
- * legacy hypercall is:
+ * **NOTE**:
+ * Versions of Xen prior to 3.0.2 provide only the following legacy version
+ * of this hypercall, supporting only the commands yield, block and shutdown:
  *  long sched_op(int cmd, unsigned long arg)
  * @cmd == SCHEDOP_??? (scheduler operation).
  * @arg == 0               (SCHEDOP_yield and SCHEDOP_block)
  *      == SHUTDOWN_* code (SCHEDOP_shutdown)
- * 
- * The sub-command descriptions below describe extra arguments for the
- * sched_op_new() hypercall.
  */
 
 /*
diff -r e04978011d2d -r 25003dd43a92 xen/include/xen/time.h
--- a/xen/include/xen/time.h    Fri Mar 17 21:26:24 2006
+++ b/xen/include/xen/time.h    Fri Mar 17 22:37:28 2006
@@ -59,6 +59,8 @@
 extern void do_settime(
     unsigned long secs, unsigned long nsecs, u64 system_time_base);
 
+extern void send_timer_event(struct vcpu *v);
+
 #endif /* __XEN_TIME_H__ */
 
 /*
diff -r e04978011d2d -r 25003dd43a92 extras/mini-os/console/console.c
--- /dev/null   Fri Mar 17 21:26:24 2006
+++ b/extras/mini-os/console/console.c  Fri Mar 17 22:37:28 2006
@@ -0,0 +1,149 @@
+/* 
+ ****************************************************************************
+ * (C) 2006 - Grzegorz Milos - Cambridge University
+ ****************************************************************************
+ *
+ *        File: console.h
+ *      Author: Grzegorz Milos
+ *     Changes: 
+ *              
+ *        Date: Mar 2006
+ * 
+ * Environment: Xen Minimal OS
+ * Description: Console interface.
+ *
+ * Handles console I/O. Defines printk.
+ *
+ ****************************************************************************
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * DEALINGS IN THE SOFTWARE.
+ */
+ 
+#include <types.h>
+#include <wait.h>
+#include <mm.h>
+#include <hypervisor.h>
+#include <events.h>
+#include <os.h>
+#include <lib.h>
+#include <xenbus.h>
+#include <xen/io/console.h>
+
+
+/* Low level functions defined in xencons_ring.c */
+extern int xencons_ring_init(void);
+extern int xencons_ring_send(const char *data, unsigned len);
+extern int xencons_ring_send_no_notify(const char *data, unsigned len);
+
+
+/* If console not initialised the printk will be sent to xen serial line 
+   NOTE: you need to enable verbose in xen/Rules.mk for it to work. */
+static int console_initialised = 0;
+
+
+void xencons_rx(char *buf, unsigned len, struct pt_regs *regs)
+{
+    if(len > 0)
+    {
+        /* Just repeat what's written */
+        buf[len] = '\0';
+        printk("%s", buf);
+        
+        if(buf[len-1] == '\r')
+            printk("\nNo console input handler.\n");
+    }
+}
+
+void xencons_tx(void)
+{
+    /* Do nothing, handled by _rx */
+}
+
+
+void console_print(char *data, int length)
+{
+    char *curr_char, saved_char;
+    int part_len;
+    int (*ring_send_fn)(const char *data, unsigned length);
+
+    if(!console_initialised)
+        ring_send_fn = xencons_ring_send_no_notify;
+    else
+        ring_send_fn = xencons_ring_send;
+        
+    for(curr_char = data; curr_char < data+length-1; curr_char++)
+    {
+        if(*curr_char == '\n')
+        {
+            saved_char = *(curr_char+1);
+            *(curr_char+1) = '\r';
+            part_len = curr_char - data + 2;
+            ring_send_fn(data, part_len);
+            *(curr_char+1) = saved_char;
+            data = curr_char+1;
+            length -= part_len - 1;
+        }
+    }
+    
+    ring_send_fn(data, length);
+    
+    if(data[length-1] == '\n')
+        ring_send_fn("\r", 1);
+}
+
+void print(int direct, const char *fmt, va_list args)
+{
+    static char   buf[1024];
+    
+    (void)vsnprintf(buf, sizeof(buf), fmt, args);
+ 
+    if(direct)
+    {
+        (void)HYPERVISOR_console_io(CONSOLEIO_write, strlen(buf), buf);
+        return;
+    }
+    
+    if(!console_initialised)
+        (void)HYPERVISOR_console_io(CONSOLEIO_write, strlen(buf), buf);
+        
+    console_print(buf, strlen(buf));
+}
+
+void printk(const char *fmt, ...)
+{
+    va_list       args;
+    va_start(args, fmt);
+    print(0, fmt, args);
+    va_end(args);        
+}
+
+void xprintk(const char *fmt, ...)
+{
+    va_list       args;
+    va_start(args, fmt);
+    print(1, fmt, args);
+    va_end(args);        
+}
+void init_console(void)
+{   
+    printk("Initialising console ... ");
+    xencons_ring_init();    
+    console_initialised = 1;
+    /* This is also required to notify the daemon */
+    printk("done.\n");
+}
diff -r e04978011d2d -r 25003dd43a92 extras/mini-os/console/xencons_ring.c
--- /dev/null   Fri Mar 17 21:26:24 2006
+++ b/extras/mini-os/console/xencons_ring.c     Fri Mar 17 22:37:28 2006
@@ -0,0 +1,104 @@
+#include <types.h>
+#include <wait.h>
+#include <mm.h>
+#include <hypervisor.h>
+#include <events.h>
+#include <os.h>
+#include <lib.h>
+#include <xenbus.h>
+#include <xen/io/console.h>
+
+
+/* TODO - need to define BUG_ON for whole mini-os, need crash-dump as well */
+extern void do_exit(void);
+#define BUG_ON(_cond)   do{if(_cond) do_exit();} while(0);
+
+static inline struct xencons_interface *xencons_interface(void)
+{
+    return mfn_to_virt(start_info.console_mfn);
+}
+
+static inline void notify_daemon(void)
+{
+    /* Use evtchn: this is called early, before irq is set up. */
+    notify_remote_via_evtchn(start_info.console_evtchn);
+}
+
+int xencons_ring_send_no_notify(const char *data, unsigned len)
+{      
+    int sent = 0;
+       struct xencons_interface *intf = xencons_interface();
+       XENCONS_RING_IDX cons, prod;
+
+       cons = intf->out_cons;
+       prod = intf->out_prod;
+       mb();
+       BUG_ON((prod - cons) > sizeof(intf->out));
+
+       while ((sent < len) && ((prod - cons) < sizeof(intf->out)))
+               intf->out[MASK_XENCONS_IDX(prod++, intf->out)] = data[sent++];
+
+       wmb();
+       intf->out_prod = prod;
+    
+    return sent;
+}
+
+int xencons_ring_send(const char *data, unsigned len)
+{
+    int sent;
+    sent = xencons_ring_send_no_notify(data, len);
+       notify_daemon();
+
+       return sent;
+}      
+
+
+
+static void handle_input(int port, struct pt_regs *regs)
+{
+       struct xencons_interface *intf = xencons_interface();
+       XENCONS_RING_IDX cons, prod;
+
+       cons = intf->in_cons;
+       prod = intf->in_prod;
+       mb();
+       BUG_ON((prod - cons) > sizeof(intf->in));
+
+       while (cons != prod) {
+               xencons_rx(intf->in+MASK_XENCONS_IDX(cons,intf->in), 1, regs);
+               cons++;
+       }
+
+       mb();
+       intf->in_cons = cons;
+
+       notify_daemon();
+
+       xencons_tx();
+}
+
+int xencons_ring_init(void)
+{
+       int err;
+
+       if (!start_info.console_evtchn)
+               return 0;
+
+       err = bind_evtchn(start_info.console_evtchn, handle_input);
+       if (err <= 0) {
+               printk("XEN console request chn bind failed %i\n", err);
+               return err;
+       }
+
+       /* In case we have in-flight data after save/restore... */
+       notify_daemon();
+
+       return 0;
+}
+
+void xencons_resume(void)
+{
+       (void)xencons_ring_init();
+}
+

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

<Prev in Thread] Current Thread [Next in Thread>