ia64/xen-unstable

changeset 1949:f9ae44cc1373

bitkeeper revision 1.1108.1.32 (4107aea3BDdUxrD2IYQ5Iqr4OuE-gA)

Merge freefall.cl.cam.ac.uk:/auto/groups/xeno/BK/xeno.bk
into freefall.cl.cam.ac.uk:/auto/groups/xeno/users/cl349/BK/xeno.bk-26dom0
author cl349@freefall.cl.cam.ac.uk
date Wed Jul 28 13:48:19 2004 +0000 (2004-07-28)
parents ae191540ab44 fe7f5c8eb34e
children b425bcf84138
files .rootkeys BitKeeper/etc/ignore docs/interface.tex docs/user.tex tools/libxc/xc_domain.c tools/misc/Makefile tools/misc/xensv tools/python/xen/lowlevel/xc/xc.c tools/python/xen/sv/CreateDomain.py tools/python/xen/sv/Daemon.py tools/python/xen/sv/HTMLBase.py tools/python/xen/sv/Wizard.py tools/python/xen/sv/Wizzard.py tools/python/xen/sv/params.py tools/python/xen/sv/util.py tools/python/xen/util/Brctl.py tools/python/xen/xend/XendClient.py tools/python/xen/xend/XendDomain.py tools/python/xen/xend/XendDomainInfo.py tools/python/xen/xend/server/SrvDomain.py tools/python/xen/xm/main.py xen/arch/x86/domain.c xen/arch/x86/memory.c xen/arch/x86/shadow.c xen/arch/x86/x86_32/mm.c xen/common/dom0_ops.c xen/common/dom_mem_ops.c xen/common/domain.c xen/common/event_channel.c xen/common/kernel.c xen/common/keyhandler.c xen/common/memory.c xen/common/page_alloc.c xen/common/sched_bvt.c xen/common/sched_fair_bvt.c xen/common/sched_rrobin.c xen/common/schedule.c xen/include/asm-x86/config.h xen/include/asm-x86/domain.h xen/include/asm-x86/mm.h xen/include/asm-x86/page.h xen/include/asm-x86/shadow.h xen/include/xen/mm.h xen/include/xen/sched-if.h xen/include/xen/sched.h
line diff
     1.1 --- a/.rootkeys	Wed Jul 28 13:45:22 2004 +0000
     1.2 +++ b/.rootkeys	Wed Jul 28 13:48:19 2004 +0000
     1.3 @@ -319,6 +319,7 @@ 3f5ef5a2dTZP0nnsFoeq2jRf3mWDDg tools/mis
     1.4  3f870808zS6T6iFhqYPGelroZlVfGQ tools/misc/xen_cpuperf.c
     1.5  405eedf6_nnNhFQ1I85lhCkLK6jFGA tools/misc/xencons
     1.6  40c9c4697z76HDfkCLdMhmaEwzFoNQ tools/misc/xend
     1.7 +4107986eMWVdBoz4tXYoOscpN_BCYg tools/misc/xensv
     1.8  4056f5155QYZdsk-1fLdjsZPFTnlhg tools/misc/xensymoops.py
     1.9  40cf2937dqM1jWW87O5OoOYND8leuA tools/misc/xm
    1.10  40c9c468icGyC5RAF1bRKsCXPDCvsA tools/python/Makefile
    1.11 @@ -381,6 +382,7 @@ 40dc4076St6AmPTmQPrtQ6LGHPxGmw tools/pyt
    1.12  40dc4076pVeE1kEEWzcUaNZin65kCA tools/python/xen/lowlevel/xu/domain_controller.h
    1.13  40dc4076CwBYRTUQDdbdU1L6KcLgSw tools/python/xen/lowlevel/xu/xu.c
    1.14  41052eb84_irpx0E9N_kqBp9eoin5g tools/python/xen/sv/CreateDomain.py
    1.15 +4107986egkTAMIHW7n-i4ShvCGWpLQ tools/python/xen/sv/Daemon.py
    1.16  40fcefb2qm13BbRZBydAatOavaS0fQ tools/python/xen/sv/DomInfo.py
    1.17  40fcefb2-RIU8GB67mJMRzybME9bxw tools/python/xen/sv/DomList.py
    1.18  40fcefb23FfQn-ZBCbcHqA0cPGqQxw tools/python/xen/sv/GenTabbed.py
    1.19 @@ -388,8 +390,9 @@ 40fcefb2QZAn3u3sX-M7NXBjOv5HGg tools/pyt
    1.20  40fcefb2vnfDbl4w_yCTedROPuqs0g tools/python/xen/sv/Main.py
    1.21  40fcefb24h-04WaHag-Tg4nxWPhTig tools/python/xen/sv/NodeInfo.py
    1.22  40fcefb2Sif__6AqrANeBQZZfvP-6w tools/python/xen/sv/TabView.py
    1.23 -41052eb8UrgtUkuJPg7oY1tutVQHsg tools/python/xen/sv/Wizzard.py
    1.24 +41052eb8UrgtUkuJPg7oY1tutVQHsg tools/python/xen/sv/Wizard.py
    1.25  40fcefb2DqteqCCZYDCvvh4Q5jBd0w tools/python/xen/sv/__init__.py
    1.26 +4107986e6qN1IdvIDdId0AYFmDMkiQ tools/python/xen/sv/params.py
    1.27  40fcefb4rnaZNjqsBu7A5V2rlLyqRw tools/python/xen/sv/util.py
    1.28  40d8915cyoVA0hJxiBFNymL7YvDaRg tools/python/xen/util/Brctl.py
    1.29  40dfd40aGqGkiopOOgJxSF4iCbHM0Q tools/python/xen/util/__init__.py
     2.1 --- a/BitKeeper/etc/ignore	Wed Jul 28 13:45:22 2004 +0000
     2.2 +++ b/BitKeeper/etc/ignore	Wed Jul 28 13:48:19 2004 +0000
     2.3 @@ -35,3 +35,14 @@ xen/xen.*
     2.4  tools/xfrd/xfrd
     2.5  xen/tools/elf-reloc
     2.6  xen/tools/figlet/figlet
     2.7 +docs/interface.aux
     2.8 +docs/interface.log
     2.9 +docs/interface.pdf
    2.10 +docs/interface.ps
    2.11 +docs/interface.toc
    2.12 +docs/user.aux
    2.13 +docs/user.log
    2.14 +docs/user.pdf
    2.15 +docs/user.ps
    2.16 +docs/user.toc
    2.17 +tools/web-shutdown.tap
     3.1 --- a/docs/interface.tex	Wed Jul 28 13:45:22 2004 +0000
     3.2 +++ b/docs/interface.tex	Wed Jul 28 13:48:19 2004 +0000
     3.3 @@ -259,37 +259,43 @@ table updates and also on remapping memo
     3.4  
     3.5  
     3.6  \chapter{Network I/O}
     3.7 -Since the hypervisor must multiplex network resources, its network subsystem
     3.8 -may be viewed as a virtual network switching element with each domain having
     3.9 -one or more virtual network interfaces to this network.
    3.10  
    3.11 -The hypervisor acts conceptually as an IP router, forwarding each domain's
    3.12 -traffic according to a set of rules.
    3.13 +Virtual network device services are provided by shared memory
    3.14 +communications with a `backend' domain.  From the point of view of
    3.15 +other domains, the backend may be viewed as a virtual ethernet switch
    3.16 +element with each domain having one or more virtual network interfaces
    3.17 +connected to it.
    3.18  
    3.19 -\section{Hypervisor Packet Handling}
    3.20 -The hypervisor is responsible primarily for {\it data-path} operations.
    3.21 +\section{Backend Packet Handling}
    3.22 +The backend driver is responsible primarily for {\it data-path} operations.
    3.23  In terms of networking this means packet transmission and reception.
    3.24  
    3.25 -On the transmission side, the hypervisor needs to perform two key actions:
    3.26 +On the transmission side, the backend needs to perform two key actions:
    3.27  \begin{itemize}
    3.28 -\item {\tt Validation:} A domain is only allowed to emit packets matching a certain
    3.29 -specification; for example, ones in which the source IP address matches
    3.30 -one assigned to the virtual interface over which it is sent. The hypervisor
    3.31 -is responsible for ensuring any such requirements are met, either by checking
    3.32 -or by stamping outgoing packets with prescribed values for certain fields.
    3.33 +\item {\tt Validation:} A domain is only allowed to emit packets
    3.34 +matching a certain specification; for example, ones in which the
    3.35 +source IP address matches one assigned to the virtual interface over
    3.36 +which it is sent. The backend is responsible for ensuring any such
    3.37 +requirements are met, either by checking or by stamping outgoing
    3.38 +packets with prescribed values for certain fields.
    3.39 +
    3.40 +Validation functions can be configured using standard firewall rules
    3.41 +(i.e. IP Tables, in the case of Linux).
    3.42  
    3.43 -\item {\tt Scheduling:} Since a number of domains can share a single ``real'' network 
    3.44 -interface, the hypervisor must mediate access when several domains each 
    3.45 -have packets queued for transmission. Of course, this general scheduling
    3.46 -function subsumes basic shaping or rate-limiting schemes.
    3.47 +\item {\tt Scheduling:} Since a number of domains can share a single
    3.48 +``real'' network interface, the hypervisor must mediate access when
    3.49 +several domains each have packets queued for transmission. Of course,
    3.50 +this general scheduling function subsumes basic shaping or
    3.51 +rate-limiting schemes.
    3.52  
    3.53 -\item {\tt Logging and Accounting:} The hypervisor can be configured with classifier 
    3.54 -rules that control how packets are accounted or logged. For example, 
    3.55 -{\it domain0} could request that it receives a log message or copy of the
    3.56 -packet whenever another domain attempts to send a TCP packet containg a 
    3.57 -SYN.
    3.58 +\item {\tt Logging and Accounting:} The hypervisor can be configured
    3.59 +with classifier rules that control how packets are accounted or
    3.60 +logged. For example, {\it domain0} could request that it receives a
    3.61 +log message or copy of the packet whenever another domain attempts to
    3.62 +send a TCP packet containg a SYN.
    3.63  \end{itemize}
    3.64 -On the recive side, the hypervisor's role is relatively straightforward:
    3.65 +
    3.66 +On the recive side, the backend's role is relatively straightforward:
    3.67  once a packet is received, it just needs to determine the virtual interface(s)
    3.68  to which it must be delivered and deliver it via page-flipping. 
    3.69  
    3.70 @@ -336,42 +342,33 @@ an event to the domain.
    3.71  
    3.72  \section{Virtual Block Devices (VBDs)}
    3.73  
    3.74 -All guest OS disk access goes through the VBD interface. The VBD interface
    3.75 -provides the administrator with the ability to selectively grant domains 
    3.76 -access to portions of block storage devices visible to the system.
    3.77 -
    3.78 -A VBD can also be comprised of a set of extents from multiple storage devices.
    3.79 -This provides the same functionality as a concatenated disk driver.
    3.80 -
    3.81 -\section{Virtual Disks (VDs)}
    3.82 +All guest OS disk access goes through the VBD interface. The VBD
    3.83 +interface provides the administrator with the ability to selectively
    3.84 +grant domains access to portions of block storage devices visible to
    3.85 +the the block backend device (usually domain 0).
    3.86  
    3.87 -VDs are an abstraction built on top of the VBD interface. One can reserve disk
    3.88 -space for use by the VD layer. This space is then managed as a pool of free extents.
    3.89 -The VD tools can automatically allocate collections of extents from this pool to
    3.90 -create ``virtual disks'' on demand. 
    3.91 +VBDs can literally be backed by any block device accessible to the
    3.92 +backend domain, including network-based block devices (iSCSI, *NBD,
    3.93 +etc), loopback devices and LVM / MD devices.
    3.94  
    3.95 -\subsection{Virtual Disk Management}
    3.96 -The VD management code consists of a set of python libraries. It can therefore
    3.97 -be accessed by custom scripts as well as the convenience scripts provided. The
    3.98 -VD database is a SQLite database in /var/db/xen\_vdisks.sqlite.
    3.99 -
   3.100 -The VD scripts and general VD usage are documented in the VBD-HOWTO.txt.
   3.101 +Old (Xen 1.2) virtual disks are not supported under Xen 2.0, since
   3.102 +similar functionality can be achieved using the (more advanced) LVM
   3.103 +system, which is already in widespread use.
   3.104  
   3.105  \subsection{Data Transfer}
   3.106  Domains which have been granted access to a logical block device are permitted
   3.107 -to read and write it directly through the hypervisor, rather than requiring
   3.108 -{\it domain0} to mediate every data access. 
   3.109 -
   3.110 -In overview, the same style of descriptor-ring that is used for network
   3.111 -packets is used here. Each domain has one ring that carries operation requests to the 
   3.112 -hypervisor and carries the results back again. 
   3.113 +to read and write it by shared memory communications with the backend domain. 
   3.114  
   3.115 -Rather than copying data in and out of the hypervisor, we use page pinning to
   3.116 -enable DMA transfers directly between the physical device and the domain's 
   3.117 -buffers. Disk read operations are straightforward; the hypervisor just needs
   3.118 -to know which pages have pending DMA transfers, and prevent the guest OS from
   3.119 -giving the page back to the hypervisor, or to use them for storing page tables.
   3.120 +In overview, the same style of descriptor-ring that is used for
   3.121 +network packets is used here. Each domain has one ring that carries
   3.122 +operation requests to the hypervisor and carries the results back
   3.123 +again.
   3.124  
   3.125 +Rather than copying data, the backend simply maps the domain's buffers
   3.126 +in order to enable direct DMA to them.  The act of mapping the buffers
   3.127 +also increases the reference counts of the underlying pages, so that
   3.128 +the unprivileged domain cannot try to return them to the hypervisor,
   3.129 +install them as page tables, or any other unsafe behaviour.
   3.130  %block API here 
   3.131  
   3.132  \chapter{Privileged operations}
   3.133 @@ -811,9 +808,7 @@ in kilobytes.
   3.134  
   3.135  {\it DOM0\_GETPAGEFRAMEINFO}:
   3.136  
   3.137 -{\it DOM0\_IOPL}:
   3.138 -
   3.139 -{\it DOM0\_MSR}:
   3.140 +{\it DOM0\_IOPL}: set IO privilege level
   3.141  
   3.142  {\it DOM0\_DEBUG}: interactively call pervasive debugger
   3.143  
   3.144 @@ -830,11 +825,13 @@ in kilobytes.
   3.145  
   3.146  {\it DOM0\_PCIDEV\_ACCESS}: modify PCI device access permissions
   3.147  
   3.148 +{\it DOM0\_SCHED\_ID}: get the ID of the current Xen scheduler
   3.149  
   3.150 -\section{network\_op(network\_op\_t *op)} 
   3.151 -update network ruleset
   3.152 +{\it DOM0\_SETDOMAINNAME}: set the name of a domain
   3.153  
   3.154 -\section{ block\_io\_op(block\_io\_op\_t *op)}
   3.155 +{\it DOM0\_SETDOMAININITIALMEM}: set initial memory allocation of a domain
   3.156 +
   3.157 +{\it DOM0\_GETPAGEFRAMEINFO2}:
   3.158  
   3.159  \section{ set\_debugreg(int reg, unsigned long value)}
   3.160  set debug register reg to value
   3.161 @@ -847,7 +844,7 @@ set debug register reg to value
   3.162  \section{ set\_fast\_trap(int idx)}
   3.163   install traps to allow guest OS to bypass hypervisor
   3.164  
   3.165 -\section{ dom\_mem\_op(dom\_mem\_op\_t *op)}
   3.166 +\section{ dom\_mem\_op(unsigned int op, void *pages, unsigned long nr\_pages)}
   3.167   increase or decrease memory reservations for guest OS
   3.168  
   3.169  \section{ multicall(multicall\_entry\_t *call\_list, int nr\_calls)}
     4.1 --- a/docs/user.tex	Wed Jul 28 13:45:22 2004 +0000
     4.2 +++ b/docs/user.tex	Wed Jul 28 13:48:19 2004 +0000
     4.3 @@ -162,7 +162,8 @@ This manual describes how to install the
     4.4  source.  Alternatively, there may be packages available for your
     4.5  operating system distribution.
     4.6  
     4.7 -Prerequisites:
     4.8 +\section{Prerequisites}
     4.9 +\label{sec:prerequisites}
    4.10  \begin{itemize}
    4.11  \item A working installation of your favourite Linux distribution.
    4.12  \item A working installation of the GRUB bootloader.
    4.13 @@ -173,33 +174,53 @@ make install-twisted} in the root of the
    4.14  \item The Linux bridge control tools (see {\tt
    4.15  http://bridge.sourceforge.net }).  There may be a packages of these
    4.16  tools available for your distribution.
    4.17 +\item Linux IP Routing Tools
    4.18 +\item make
    4.19 +\item python-dev
    4.20 +\item gcc
    4.21 +\item zlib-dev
    4.22 +\item libcurl
    4.23 +\item python2.3-pycurl
    4.24 +\item python2.3-twisted
    4.25  \end{itemize}
    4.26  
    4.27 -Optional:
    4.28 +\section{Optional}
    4.29  \begin{itemize}
    4.30  \item The Python logging package (see {\tt http://www.red-dove.com/})
    4.31  for additional Xend logging functionality.
    4.32  \end{itemize}
    4.33  
    4.34 -\section{Download the Xen source code}
    4.35 -
    4.36 -The public master BK repository for the 2.0 release lives at:
    4.37 -{\tt bk://xen.bkbits.net/xeno-unstable.bk}.
    4.38 +\section{Install Bitkeeper (Optional)}
    4.39  
    4.40  To fetch a local copy, first download the BitKeeper tools at: {\tt
    4.41  http://www.bitmover.com/download } with username 'bitkeeper' and
    4.42  password 'get bitkeeper'.
    4.43  
    4.44 -Then install the tools and then run:
    4.45 +The BitKeeper install program is designed to be run with X.  If X is
    4.46 +not available, you can specify the install directory on the command
    4.47 +line.
    4.48 +
    4.49 +\section{Download the Xen source code}
    4.50 +
    4.51 +\subsection{Using Bitkeeper}
    4.52 +
    4.53 +The public master BK repository for the 2.0 release lives at:
    4.54 +{\tt bk://xen.bkbits.net/xeno-unstable.bk}.
    4.55 +
    4.56 +Change to the directory in which you want to put the source code, then
    4.57 +run:
    4.58  \begin{verbatim}
    4.59  # bk clone bk://xen.bkbits.net/xeno-unstable.bk
    4.60  \end{verbatim}
    4.61  
    4.62  Under your current directory, a new directory named 'xeno-unstable.bk'
    4.63 -has been created, which contains all the necessary source code for the
    4.64 -Xen hypervisor and Linux guest OSes.
    4.65 +has been created, which contains all the source code for the Xen
    4.66 +hypervisor and the Xen tools.  The directory also contains `sparse'
    4.67 +Linux source trees, containing only the files that differ between
    4.68 +XenLinux and standard Linux.
    4.69  
    4.70 -To update to the newest changes to the repository, run
    4.71 +Once you have cloned the repository, you can update to the newest
    4.72 +changes to the repository by running:
    4.73  \begin{verbatim}
    4.74  # cd xeno-unstable.bk # to change into the local repository
    4.75  # bk pull             # to update the repository
    4.76 @@ -227,7 +248,7 @@ following:
    4.77  \begin{itemize}
    4.78  \item Build Xen
    4.79  \item Build the control tools, including Xend
    4.80 -\item Download the ebtables patch
    4.81 +\item Download the ebtables patch for Linux 2.4
    4.82  \item Download (if necessary) and unpack the Linux 2.4 source code,
    4.83        and patch it for use with Xen
    4.84  \item Build a Linux kernel to use in domain 0 and a smaller
    4.85 @@ -258,16 +279,17 @@ destinations.
    4.86  
    4.87  \section{Configuration}
    4.88  
    4.89 -\subsection{\path{grub.conf}}
    4.90 +\subsection{GRUB Configuration}
    4.91  
    4.92  An entry should be added to \path{grub.conf} (often found under
    4.93 -\path{/boot/grub.conf} or \path{/boot/grub/grub.conf}) to allow Xen /
    4.94 -XenLinux to boot.  The entry should look something like the following:
    4.95 +\path{/boot/} or \path{/boot/grub/}) to allow Xen / XenLinux to boot.
    4.96 +This file is sometimes called \path{menu.lst}, depending on your
    4.97 +distribution.  The entry should look something like the following:
    4.98  
    4.99  \begin{verbatim}
   4.100  title Xen 2.0 / XenoLinux 2.4.26
   4.101          kernel /boot/xen.gz dom0_mem=131072 com1=115200,8n1
   4.102 -        module /boot/xenolinux.gz root=/dev/sda4 ro console=tty0
   4.103 +        module /boot/xenolinux.gz root=/dev/sda4 ro console=tty0 console=ttyS0
   4.104  \end{verbatim}
   4.105  
   4.106  The first line of the configuration (kernel...) tells GRUB where to
   4.107 @@ -276,6 +298,11 @@ second line of the configuration describ
   4.108  XenoLinux kernel that Xen should start and the parameters that should
   4.109  be passed to it.
   4.110  
   4.111 +As always when installing a new kernel, it is recommended that you do
   4.112 +not remove the original contents of \path{grub.conf} --- you may want
   4.113 +to boot up with your old Linux kernel in future, particularly if you
   4.114 +have problems.
   4.115 +
   4.116  \subsection{Serial Console}
   4.117  
   4.118  In order to configure serial console output, it is necessary to add a
   4.119 @@ -285,6 +312,26 @@ serial console.  Add the line:
   4.120  
   4.121  {\tt c:2345:respawn:/sbin/mingetty ttyS0}
   4.122  
   4.123 +\section{Test the new install}
   4.124 +
   4.125 +It should now be possible to restart the system and use Xen.  Reboot
   4.126 +as usual but choose the new Xen option when the Grub screen appears.
   4.127 +
   4.128 +What follows should look much like a conventional Linux boot.  The
   4.129 +first portion of the output comes from Xen itself, supplying low level
   4.130 +information about itself and the machine it is running on.  The
   4.131 +following portion of the output comes from XenLinux itself.
   4.132 +
   4.133 +You may see some errors during the XenLinux boot.  These are not
   4.134 +necessarily anything to worry about --- they may result from kernel
   4.135 +configuration differences between your XenLinux kernel and the one you
   4.136 +usually use.
   4.137 +
   4.138 +When the boot completes, you should be able to log into your system as
   4.139 +usual.  If you are unable to log in to your system running Xen, you
   4.140 +should still be able to reboot with your normal Linux kernel.
   4.141 +
   4.142 +
   4.143  \chapter{Starting a domain}
   4.144  
   4.145  The first step in creating a new domain is to prepare a root
   4.146 @@ -295,6 +342,11 @@ A simple way to do this is simply to boo
   4.147  install CD and install the distribution into another partition on your
   4.148  hard drive.
   4.149  
   4.150 +{\em N.b } you can boot with Xen and XenLinux without installing any
   4.151 +special userspace tools but will need to have the prerequisites
   4.152 +described in Section~\ref{sec:prerequisites} and the Xen control tools
   4.153 +are installed before you proceed.
   4.154 +
   4.155  \section{From the web interface}
   4.156  
   4.157  \begin{itemize}
   4.158 @@ -335,6 +387,12 @@ domains). [i.e. {\tt disk = ['phy:your\_
   4.159  receive its IP address from a DHCP server. [i.e. {\tt dhcp=''dhcp''}]
   4.160  \end{description}
   4.161  
   4.162 +You may also want to edit the {\bf vif} variable in order to choose
   4.163 +the MAC address of the virtual ethernet interface yourself.  For
   4.164 +example: \\ \verb_vif = [`mac=00:06:AA:F6:BB:B3']_\\ If you do not set
   4.165 +this variable, Xend will automatically generate a random MAC address
   4.166 +from an unused range.
   4.167 +
   4.168  \subsection{Starting the domain}
   4.169  
   4.170  The {\tt xm} tool provides a variety of commands for managing domains.
   4.171 @@ -351,8 +409,86 @@ the {\tt xmdefaults} file.  The tool use
   4.172  \path{/etc/xen/xmdefaults} file, since no custom configuration file
   4.173  was specified on the command line.
   4.174  
   4.175 +\chapter{Domain management tasks}
   4.176 +
   4.177 +The previous chapter described a simple example of how to configure
   4.178 +and start a domain.  This chapter summarises the tools available to
   4.179 +manage running domains.
   4.180 +
   4.181 +\section{Command line management}
   4.182 +
   4.183 +Command line management tasks are also performed using the {\tt xm}
   4.184 +tool.  For online help for the commands available, type:\\
   4.185 +\verb_# xm help_
   4.186 +
   4.187 +\subsection{Basic management commands}
   4.188 +
   4.189 +The most important {\tt xm} commands are: \\
   4.190 +\verb_# xm list_ : Lists all domains running. \\
   4.191 +\verb_# xm consoles_ : Gives information about the domain consoles. \\
   4.192 +\verb_# xm console_: open a console to a domain.
   4.193 +e.g. \verb_# xm console 1_ (open console to domain 1)
   4.194 +
   4.195   XXX More explanation needed here...
   4.196  
   4.197 +\chapter{Other kinds of storage}
   4.198 +
   4.199 +It is possible to use any Linux block device to store virtual machine
   4.200 +disk images.  This chapter covers some of the possibilities; note that
   4.201 +it is also possible to use network-based block devices and other
   4.202 +unconventional block devices.
   4.203 +
   4.204 +\section{File-backed virtual block devices}
   4.205 +
   4.206 +It is possible to use a file in Domain 0 as the primary storage for a
   4.207 +virtual machine.  As well as being convenient, this also has the
   4.208 +advantage that the virtual block device will be {\em sparse} --- space
   4.209 +will only really be allocated as parts of the file are used.  So if a
   4.210 +virtual machine uses only half its disk space then the file really
   4.211 +takes up a half of the size allocated.
   4.212 +
   4.213 +For example, to create a 2GB sparse file-backed virtual block device
   4.214 +(actually only consumes 1KB of disk):
   4.215 +
   4.216 +\verb_# dd if=/dev/zero of=vm1disk bs=1k seek=2048k count=1_
   4.217 +
   4.218 +Choose a free loop back device, and attach file: \\
   4.219 +\verb_# losetup /dev/loop0 vm1disk_ \\
   4.220 +Make a file system on the loop back device: \\
   4.221 +\verb_# mkfs ­t ext3 /dev/loop0_
   4.222 +
   4.223 +Populate the file system e.g. by copying from the current root:
   4.224 +\begin{verbatim}
   4.225 +# mount /dev/loop0 /mnt
   4.226 +# cp -ax / /mnt
   4.227 +\end{verbatim}
   4.228 +Tailor the file system by editing \path{/etc/fstab},
   4.229 +\path{/etc/hostname}, etc (don't forget to edit the files in the
   4.230 +mounted file system, instead of your domain 0 filesystem, e.g. you
   4.231 +would edit \path{/mnt/etc/fstab} instead of \path{/etc/fstab} ).  For
   4.232 +this example put \path{/dev/sda1} to root in fstab.
   4.233 +
   4.234 +Now unmount (this is important!):\\
   4.235 +\verb_# umount /dev/loop0_
   4.236 +
   4.237 +In the configuration file set:\\
   4.238 +\verb_disk = [`phy:loop0,sda1,w']_
   4.239 +
   4.240 +As the virtual machine writes to its `disk', the sparse file will be
   4.241 +filled in and consume more space up to the original 2GB.
   4.242 +
   4.243 +{\em NB.} You will need to use {\tt losetup} to bind the file to
   4.244 +\path{/dev/loop0} (or whatever loopback device you chose) each time
   4.245 +you reboot domain 0.  In the near future, Xend will track which loop
   4.246 +devices are currently free and do binding itself, making this manual
   4.247 +effort unnecessary.
   4.248 +
   4.249 +\section{LVM-backed virtual block devices}
   4.250 +
   4.251 +XXX Put some simple examples here - would be nice if an LVM user could
   4.252 +contribute some, although obviously users would have to read the LVM
   4.253 +docs to do advanced stuff.
   4.254 +
   4.255  \part{Quick Reference}
   4.256  
   4.257  \chapter{Domain Configuration Files}
   4.258 @@ -670,6 +806,50 @@ administration privileges.
   4.259  IO privileges can be assigned to allow a domain to drive PCI devices
   4.260  itself.  This is used for to support driver domains.
   4.261  
   4.262 +Setting backend privileges is currently only supported in SXP format
   4.263 +config files (??? is this true - there's nothing in xmdefaults,
   4.264 +anyhow).  To allow a domain to function as a backend for others,
   4.265 +somewhere within the {\tt vm} element of its configuration file must
   4.266 +be a {\tt backend} element of the form {\tt (backend ({\em type}))}
   4.267 +where {\tt \em type} may be either {\tt netif} or {\tt blkif},
   4.268 +according to the type of virtual device this domain will service.
   4.269 +After this domain has been built, Xend will connect all new and
   4.270 +existing {\em virtual} devices (of the appropriate type) to that
   4.271 +backend.
   4.272 +
   4.273 +Note that:
   4.274 +\begin{itemize}
   4.275 +\item a block backend cannot import virtual block devices from other
   4.276 +domains
   4.277 +\item a network backend cannot import virtual network devices from
   4.278 +other domains
   4.279 +\end{itemize}
   4.280 +
   4.281 +Thus (particularly in the case of block backends, which cannot import
   4.282 +a virtual block device as their root filesystem), you may need to boot
   4.283 +a backend domain from a ramdisk or a network device.
   4.284 +
   4.285 +The privilege to drive PCI devices may also be specified on a
   4.286 +per-device basis.  Xen will assign the minimal set of hardware
   4.287 +privileges to a domain that are required to control its devices.  This
   4.288 +can be configured in either format of configuration file:
   4.289 +
   4.290 +\begin{itemize}
   4.291 +\item SXP Format:
   4.292 +  Include {\tt device} elements
   4.293 +  {\tt (device (pci (bus {\em x}) (dev {\em y}) (func {\em z}))) } \\
   4.294 +  inside the top-level {\tt vm} element.  Each one specifies the address
   4.295 +  of a device this domain is allowed to drive ---
   4.296 +  the numbers {\em x},{\em y} and {\em z} may be in either decimal or
   4.297 +  hexadecimal format.
   4.298 +\item Flat Format: Include a list of PCI device addresses of the
   4.299 +  format: \\ {\tt pci = ['x,y,z', ...] } \\ where each element in the
   4.300 +  list is a string specifying the components of the PCI device
   4.301 +  address, separated by commas.  The components ({\tt \em x}, {\tt \em
   4.302 +  y} and {\tt \em z}) of the list may be formatted as either decimal
   4.303 +  or hexadecimal.
   4.304 +\end{itemize}
   4.305 +
   4.306  \section{Administration Domains}
   4.307  
   4.308  Administration privileges allow a domain to use the ``dom0
   4.309 @@ -812,4 +992,44 @@ domain).  Device IDs should be given in 
   4.310  not need to be hidden --- they are hidden implicitly, since guest OSes
   4.311  do not need to configure them.
   4.312  
   4.313 +\chapter{Further Support}
   4.314 +
   4.315 +If you have questions that are not answered by this manual, the
   4.316 +sources of information listed below may be of interest to you.  Note
   4.317 +that bug reports, suggestions and contributions related to the
   4.318 +software (or the documentation) should be sent to the Xen developers'
   4.319 +mailing list (address below).
   4.320 +
   4.321 +\section{Other documentation}
   4.322 +
   4.323 +For developers interested in porting operating systems to Xen, the
   4.324 +{\em Xen Interface Manual} is distributed in the \path{docs/}
   4.325 +directory of the Xen source distribution.
   4.326 +
   4.327 +\section{Online references}
   4.328 +
   4.329 +The official Xen web site is found at: \\
   4.330 +{\tt
   4.331 +http://www.cl.cam.ac.uk/Research/SRG/netos/xen/] }.
   4.332 +
   4.333 +Links to other
   4.334 +documentation sources are listed at: \\ {\tt
   4.335 +http://www.cl.cam.ac.uk/Research/SRG/netos/xen/documentation.html}.
   4.336 +
   4.337 +\section{Mailing lists}
   4.338 +
   4.339 +There are currently two official Xen mailing lists:
   4.340 +
   4.341 +\begin{description}
   4.342 +\item[xen-devel@lists.sourceforge.net] Used for development
   4.343 +discussions and requests for help.  Subscribe at: \\
   4.344 +http://lists.sourceforge.net/mailman/listinfo/xen-devel
   4.345 +\item[xen-announce@lists.sourceforge.net] Used for announcements only.
   4.346 +Subscribe at: \\ http://lists.sourceforge.net/mailman/listinfo/xen-announce
   4.347 +\end{description}
   4.348 +
   4.349 +Although there is no specific user support list, the developers try to
   4.350 +assist users who post on xen-devel.  As the bulk of traffic on this
   4.351 +list increases, a dedicated user support list may be introduced.
   4.352 +
   4.353  \end{document}
     5.1 --- a/tools/libxc/xc_domain.c	Wed Jul 28 13:45:22 2004 +0000
     5.2 +++ b/tools/libxc/xc_domain.c	Wed Jul 28 13:48:19 2004 +0000
     5.3 @@ -105,7 +105,7 @@ int xc_domain_getinfo(int xc_handle,
     5.4              DOMFLAGS_SHUTDOWNMASK;
     5.5  
     5.6          info->nr_pages = op.u.getdomaininfo.tot_pages;
     5.7 -        info->max_memkb = op.u.getdomaininfo.max_pages<<(PAGE_SHIFT-10);
     5.8 +        info->max_memkb = op.u.getdomaininfo.max_pages<<(PAGE_SHIFT);
     5.9          info->shared_info_frame = op.u.getdomaininfo.shared_info_frame;
    5.10          info->cpu_time = op.u.getdomaininfo.cpu_time;
    5.11          strncpy(info->name, op.u.getdomaininfo.name, XC_DOMINFO_MAXNAME);
     6.1 --- a/tools/misc/Makefile	Wed Jul 28 13:45:22 2004 +0000
     6.2 +++ b/tools/misc/Makefile	Wed Jul 28 13:48:19 2004 +0000
     6.3 @@ -21,7 +21,7 @@ OBJS     = $(patsubst %.c,%.o,$(SRCS))
     6.4  TARGETS  = xen_cpuperf
     6.5  
     6.6  INSTALL_BIN  = $(TARGETS) xencons
     6.7 -INSTALL_SBIN = netfix xm xend
     6.8 +INSTALL_SBIN = netfix xm xend xensv
     6.9  
    6.10  all: $(TARGETS)
    6.11  	$(MAKE) -C miniterm
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/tools/misc/xensv	Wed Jul 28 13:48:19 2004 +0000
     7.3 @@ -0,0 +1,134 @@
     7.4 +#!/usr/bin/env python
     7.5 +#  -*- mode: python; -*-
     7.6 +#============================================================================
     7.7 +# Copyright (C) 2004 Tom Wilkie <tw275@cl.cam.ac.uk>
     7.8 +# Copyright (C) 2004 Mike Wray  <mike.wray@hp.com>
     7.9 +#============================================================================
    7.10 +
    7.11 +"""SV web interface Lives in /usr/sbin.
    7.12 +   Provides pretty HTML management interface.
    7.13 +
    7.14 +   Run:
    7.15 +
    7.16 +   sv start
    7.17 +
    7.18 +   The daemon is stopped with:
    7.19 +
    7.20 +   sv stop
    7.21 +   
    7.22 +   The daemon will be accessible from http://localhost:8080/
    7.23 +"""
    7.24 +import os
    7.25 +import sys
    7.26 +import re
    7.27 +
    7.28 +from xen.xend.server.params import PID_FILE as XEND_PID_FILE
    7.29 +
    7.30 +class CheckError(ValueError):
    7.31 +    pass
    7.32 +
    7.33 +def hline():
    7.34 +    print >>sys.stderr, "*" * 70
    7.35 +
    7.36 +def msg(message):
    7.37 +    print >>sys.stderr, "*" * 3, message
    7.38 +
    7.39 +def check_logging():
    7.40 +    """Check python logging is installed and raise an error if not.
    7.41 +    Logging is standard from Python 2.3 on.
    7.42 +    """
    7.43 +    try:
    7.44 +        import logging
    7.45 +    except ImportError:
    7.46 +        hline()
    7.47 +        msg("Python logging is not installed.")
    7.48 +        msg("Use 'make install-logging' at the xen root to install.")
    7.49 +        msg("")
    7.50 +        msg("Alternatively download and install from")
    7.51 +        msg("http://www.red-dove.com/python_logging.html")
    7.52 +        hline()
    7.53 +        raise CheckError("logging is not installed")
    7.54 +
    7.55 +def check_twisted_version():
    7.56 +    """Check twisted is installed with a supported version and print a warning if not.
    7.57 +    Raises an error if twisted is not installed.
    7.58 +    """
    7.59 +    # Supported twisted release and major version.
    7.60 +    RELEASE = 1
    7.61 +    MAJOR   = 3
    7.62 +    try:
    7.63 +        from twisted.copyright import version
    7.64 +    except ImportError:
    7.65 +        hline()
    7.66 +        msg("The Twisted framework is not installed.")
    7.67 +        msg("Use 'make install-twisted' at the xen root to install.")
    7.68 +        msg("")
    7.69 +        msg("Alternatively download and install version %d.%d or higher" % (RELEASE, MAJOR))
    7.70 +        msg("from http://www.twistedmatrix.com/products")
    7.71 +        hline()
    7.72 +        raise CheckError("twisted is not installed")
    7.73 +        
    7.74 +    
    7.75 +    (release, major, minor) = version.split('.')
    7.76 +    release = int(release)
    7.77 +    major = int(major)
    7.78 +    if release > RELEASE: return
    7.79 +    if release == RELEASE and major >= MAJOR: return
    7.80 +    hline()
    7.81 +    msg("Warning: Twisted version not supported: %s" % version)
    7.82 +    msg("Use Twisted version %d.%d.0 or higher" % (RELEASE, MAJOR))
    7.83 +    hline()
    7.84 +    
    7.85 +def check_xend():
    7.86 +    """Check xend is running
    7.87 +    """
    7.88 +    
    7.89 +    if not os.path.isfile(XEND_PID_FILE) or not os.path.getsize(XEND_PID_FILE):
    7.90 +    	hline()
    7.91 +        msg( "Warning: Xend has not been detected as running." )
    7.92 +        msg( "Please start it immediately with: xend start " )
    7.93 +        hline()
    7.94 +        return 0
    7.95 +        
    7.96 +    # Read the pid of the previous invocation and search active process list.
    7.97 +    pid = open(XEND_PID_FILE, 'r').read()
    7.98 +    lines = os.popen('ps ' + pid + ' 2>/dev/null').readlines()
    7.99 +    for line in lines:
   7.100 +        if re.search('^ *' + pid + '.+xend', line):
   7.101 +            return 1
   7.102 +
   7.103 +    hline()
   7.104 +    msg( "Warning: Xend has not been detected as running." )
   7.105 +    msg( "Please start it immediately with: xend start " )
   7.106 +    hline() 
   7.107 +    return 0
   7.108 +    
   7.109 +def main():
   7.110 +    try:
   7.111 +        check_logging()
   7.112 +        check_twisted_version()
   7.113 +        check_xend()
   7.114 +    except CheckError:
   7.115 +        sys.exit(1)
   7.116 +    
   7.117 +    from xen.sv import Daemon
   7.118 +
   7.119 +    daemon = Daemon.instance()
   7.120 +    
   7.121 +    if not sys.argv[1:]:
   7.122 +        print 'usage: %s {start|stop|restart}' % sys.argv[0]
   7.123 +    elif os.fork():
   7.124 +        pid, status = os.wait()
   7.125 +        return status >> 8
   7.126 +    elif sys.argv[1] == 'start':
   7.127 +        return daemon.start()
   7.128 +    elif sys.argv[1] == 'stop':
   7.129 +        return daemon.stop()
   7.130 +    elif sys.argv[1] == 'restart':
   7.131 +        return daemon.stop() or daemon.start()
   7.132 +    else:
   7.133 +        print 'not an option:', sys.argv[1]
   7.134 +    return 1
   7.135 +
   7.136 +if __name__ == '__main__':
   7.137 +    sys.exit(main())
     8.1 --- a/tools/python/xen/lowlevel/xc/xc.c	Wed Jul 28 13:45:22 2004 +0000
     8.2 +++ b/tools/python/xen/lowlevel/xc/xc.c	Wed Jul 28 13:48:19 2004 +0000
     8.3 @@ -906,15 +906,15 @@ static PyObject *pyxc_domain_setmaxmem(P
     8.4      XcObject *xc = (XcObject *)self;
     8.5  
     8.6      u32 dom;
     8.7 -    unsigned long max_memkb;
     8.8 +    unsigned long maxmem_kb;
     8.9  
    8.10 -    static char *kwd_list[] = { "dom", "max_memkb", NULL };
    8.11 +    static char *kwd_list[] = { "dom", "maxmem_kb", NULL };
    8.12  
    8.13      if ( !PyArg_ParseTupleAndKeywords(args, kwds, "ii", kwd_list, 
    8.14 -                                      &dom, &max_memkb) )
    8.15 +                                      &dom, &maxmem_kb) )
    8.16          return NULL;
    8.17  
    8.18 -    if ( xc_domain_setmaxmem(xc->xc_handle, dom, max_memkb) != 0 )
    8.19 +    if ( xc_domain_setmaxmem(xc->xc_handle, dom, maxmem_kb) != 0 )
    8.20          return PyErr_SetFromErrno(xc_error);
    8.21      
    8.22      Py_INCREF(zero);
    8.23 @@ -980,6 +980,7 @@ static PyMethodDef pyxc_methods[] = {
    8.24        " blocked  [int]:  Bool - is the domain blocked waiting for an event?\n"
    8.25        " running  [int]:  Bool - is the domain currently running?\n"
    8.26        " mem_kb   [int]:  Memory reservation, in kilobytes\n"
    8.27 +      " maxmem_kb [int]: Maximum memory limit, in kilobytes\n"
    8.28        " cpu_time [long]: CPU time consumed, in nanoseconds\n"
    8.29        " name     [str]:  Identifying name\n"
    8.30        " shutdown_reason [int]: Numeric code from guest OS, explaining "
    8.31 @@ -1228,7 +1229,7 @@ static PyMethodDef pyxc_methods[] = {
    8.32        METH_VARARGS | METH_KEYWORDS, "\n"
    8.33        "Set a domain's memory limit\n"
    8.34        " dom [int]: Identifier of domain.\n"
    8.35 -      " max_memkb [long]: .\n"
    8.36 +      " maxmem_kb [long]: .\n"
    8.37        "Returns: [int] 0 on success; -1 on error.\n" },
    8.38  
    8.39      { NULL, NULL, 0, NULL }
     9.1 --- a/tools/python/xen/sv/CreateDomain.py	Wed Jul 28 13:45:22 2004 +0000
     9.2 +++ b/tools/python/xen/sv/CreateDomain.py	Wed Jul 28 13:48:19 2004 +0000
     9.3 @@ -1,6 +1,6 @@
     9.4 -from xen.sv.Wizzard import Wizzard, Sheet
     9.5 +from xen.sv.Wizard import Wizard, Sheet
     9.6  
     9.7 -class CreateDomain( Wizzard ):
     9.8 +class CreateDomain( Wizard ):
     9.9      def __init__( self, urlWriter ):
    9.10      	
    9.11      	sheets = { 0: CreatePage0,
    9.12 @@ -8,36 +8,39 @@ class CreateDomain( Wizzard ):
    9.13            	   2: CreatePage2,
    9.14                     3: CreatePage3 }
    9.15      
    9.16 -    	Wizzard.__init__( self, urlWriter, "Create Domain Wizzard", sheets )
    9.17 +    	Wizard.__init__( self, urlWriter, "Create Domain Wizard", sheets )
    9.18         
    9.19  class CreatePage0( Sheet ):
    9.20  
    9.21      def __init__( self, urlWriter ):
    9.22      
    9.23 -    	feilds = [( 'name', 'Name')]
    9.24 +    	feilds = [( 'name', 'VM Name:'),
    9.25 +                  ( 'memory', 'RAM (Mb):' )]
    9.26      
    9.27 -        Sheet.__init__( self, urlWriter, feilds, "Create New Domain - 1" )
    9.28 +        Sheet.__init__( self, urlWriter, feilds, "Create New Domain", 0 )
    9.29                  
    9.30  class CreatePage1( Sheet ):
    9.31  
    9.32      def __init__( self, urlWriter ):
    9.33      
    9.34 -    	feilds = [( 'name', 'Name')]
    9.35 +    	feilds = [( 'kernel_type', 'Kernel Type:'),
    9.36 +                  ( 'kernel_location', 'Kernel location:')]
    9.37          
    9.38 -        Sheet.__init__( self, urlWriter, feilds, "Create New Domain - 2" )
    9.39 +        Sheet.__init__( self, urlWriter, feilds, "Setup Kernel Image", 1 )
    9.40          
    9.41  class CreatePage2( Sheet ):
    9.42  
    9.43      def __init__( self, urlWriter ):
    9.44      
    9.45 -    	feilds = [( 'name', 'Name')]    
    9.46 +    	feilds = [( 'vbd_dom0', 'Location of vbd:'),
    9.47 +        	  ( 'vbd_dom0', 'Vitualised location:')]    
    9.48     
    9.49 -        Sheet.__init__( self, urlWriter, feilds, "Create New Domain - 3" )
    9.50 +        Sheet.__init__( self, urlWriter, feilds, "Setup Virtual Block Devices", 2 )
    9.51                  
    9.52  class CreatePage3( Sheet ):
    9.53  
    9.54      def __init__( self, urlWriter ):
    9.55      
    9.56 -    	feilds = [( 'name', 'Name')]
    9.57 +    	feilds = [( 'vifs', 'Number of Vifs:')]
    9.58          
    9.59 -        Sheet.__init__( self, urlWriter, feilds, "Create New Domain - 4" )       
    9.60 \ No newline at end of file
    9.61 +        Sheet.__init__( self, urlWriter, feilds, "Create New Domain - 4", 3 )       
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/tools/python/xen/sv/Daemon.py	Wed Jul 28 13:48:19 2004 +0000
    10.3 @@ -0,0 +1,108 @@
    10.4 +###########################################################
    10.5 +## XenSV Web Control Interface Daemon
    10.6 +## Copyright (C) 2004, K A Fraser (University of Cambridge)
    10.7 +## Copyright (C) 2004, Mike Wray <mike.wray@hp.com>
    10.8 +## Copyright (C) 2004, Tom Wilkie <tw275@cam.ac.uk>
    10.9 +###########################################################
   10.10 +
   10.11 +import os
   10.12 +import os.path
   10.13 +import sys
   10.14 +import re
   10.15 +
   10.16 +from xen.sv.params import *
   10.17 +
   10.18 +from twisted.internet import reactor
   10.19 +from twisted.web import static, server, script
   10.20 +
   10.21 +class Daemon:
   10.22 +    """The xend daemon.
   10.23 +    """
   10.24 +    def __init__(self):
   10.25 +        self.shutdown = 0
   10.26 +        self.traceon = 0
   10.27 +
   10.28 +    def daemon_pids(self):
   10.29 +        pids = []
   10.30 +        pidex = '(?P<pid>\d+)'
   10.31 +        pythonex = '(?P<python>\S*python\S*)'
   10.32 +        cmdex = '(?P<cmd>.*)'
   10.33 +        procre = re.compile('^\s*' + pidex + '\s*' + pythonex + '\s*' + cmdex + '$')
   10.34 +        xendre = re.compile('^/usr/sbin/xend\s*(start|restart)\s*.*$')
   10.35 +        procs = os.popen('ps -e -o pid,args 2>/dev/null')
   10.36 +        for proc in procs:
   10.37 +            pm = procre.match(proc)
   10.38 +            if not pm: continue
   10.39 +            xm = xendre.match(pm.group('cmd'))
   10.40 +            if not xm: continue
   10.41 +            #print 'pid=', pm.group('pid'), 'cmd=', pm.group('cmd')
   10.42 +            pids.append(int(pm.group('pid')))
   10.43 +        return pids
   10.44 +
   10.45 +    def new_cleanup(self, kill=0):
   10.46 +        err = 0
   10.47 +        pids = self.daemon_pids()
   10.48 +        if kill:
   10.49 +            for pid in pids:
   10.50 +                print "Killing daemon pid=%d" % pid
   10.51 +                os.kill(pid, signal.SIGHUP)
   10.52 +        elif pids:
   10.53 +            err = 1
   10.54 +            print "Daemon already running: ", pids
   10.55 +        return err
   10.56 +            
   10.57 +    def cleanup(self, kill=False):
   10.58 +        # No cleanup to do if PID_FILE is empty.
   10.59 +        if not os.path.isfile(PID_FILE) or not os.path.getsize(PID_FILE):
   10.60 +            return 0
   10.61 +        # Read the pid of the previous invocation and search active process list.
   10.62 +        pid = open(PID_FILE, 'r').read()
   10.63 +        lines = os.popen('ps ' + pid + ' 2>/dev/null').readlines()
   10.64 +        for line in lines:
   10.65 +            if re.search('^ *' + pid + '.+xensv', line):
   10.66 +                if not kill:
   10.67 +                    print "Daemon is already running (pid %d)" % int(pid)
   10.68 +                    return 1
   10.69 +                # Old daemon is still active: terminate it.
   10.70 +                os.kill(int(pid), 1)
   10.71 +        # Delete the stale PID_FILE.
   10.72 +        os.remove(PID_FILE)
   10.73 +        return 0
   10.74 +
   10.75 +    def start(self, trace=0):
   10.76 +        if self.cleanup(kill=False):
   10.77 +            return 1
   10.78 +   
   10.79 +        # Fork -- parent writes PID_FILE and exits.
   10.80 +        pid = os.fork()
   10.81 +        if pid:
   10.82 +            # Parent
   10.83 +            pidfile = open(PID_FILE, 'w')
   10.84 +            pidfile.write(str(pid))
   10.85 +            pidfile.close()
   10.86 +            return 0
   10.87 +        # Child
   10.88 +        self.run()
   10.89 +        return 0
   10.90 +
   10.91 +    def stop(self):
   10.92 +        return self.cleanup(kill=True)
   10.93 +
   10.94 +    def run(self):
   10.95 +	root = static.File( SV_ROOT )
   10.96 +        root.indexNames = [ 'Main.rpy' ]
   10.97 +        root.processors = { '.rpy': script.ResourceScript }
   10.98 +        reactor.listenTCP( SV_PORT, server.Site( root ) )
   10.99 +        reactor.run()
  10.100 +
  10.101 +    def exit(self):
  10.102 +        reactor.diconnectAll()
  10.103 +        sys.exit(0)
  10.104 +
  10.105 +def instance():
  10.106 +    global inst
  10.107 +    try:
  10.108 +        inst
  10.109 +    except:
  10.110 +        inst = Daemon()
  10.111 +    return inst
    11.1 --- a/tools/python/xen/sv/HTMLBase.py	Wed Jul 28 13:45:22 2004 +0000
    11.2 +++ b/tools/python/xen/sv/HTMLBase.py	Wed Jul 28 13:48:19 2004 +0000
    11.3 @@ -25,9 +25,9 @@ class HTMLBase( Resource ):
    11.4          request.write( '<html><head><title>Xen</title><link rel="stylesheet" type="text/css" href="inc/style.css" />' )
    11.5          request.write( '<script src="inc/script.js"></script>' )
    11.6          request.write( '</head><body>' )
    11.7 +        request.write('<form method="post" action="%s">' % request.uri)
    11.8  
    11.9      def write_BOTTOM( self, request ):
   11.10 -        request.write('<form method="post" action="%s">' % request.uri)
   11.11          request.write('<input type="hidden" name="op" value="">')
   11.12          request.write('</form>')
   11.13          request.write( "</body></html>" )
    12.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.2 +++ b/tools/python/xen/sv/Wizard.py	Wed Jul 28 13:48:19 2004 +0000
    12.3 @@ -0,0 +1,112 @@
    12.4 +from xen.sv.util import *
    12.5 +from xen.sv.HTMLBase import HTMLBase
    12.6 +from xen.xend import sxp
    12.7 +
    12.8 +DEBUG = 1
    12.9 +
   12.10 +class Wizard( HTMLBase ):
   12.11 +
   12.12 +    def __init__( self, urlWriter, title, sheets ):
   12.13 +        HTMLBase.__init__( self )
   12.14 +        self.title = title
   12.15 +        self.sheets = sheets
   12.16 +        self.urlWriter = urlWriter
   12.17 +        
   12.18 +    def write_MENU( self, request ):
   12.19 +    	request.write( "<p class='small'><a href='%s'>%s</a></p>" % (self.urlWriter( '' ), self.title) ) 
   12.20 +    
   12.21 +    def write_BODY( self, request ):
   12.22 +        
   12.23 +   	request.write( "<table width='100%' border='0' cellspacing='0' cellpadding='0'><tr><td>" )
   12.24 +        request.write( "<p align='center'><u>%s</u></p></td></tr><tr><td>" % self.title )
   12.25 +        
   12.26 +        currSheet = getVar( 'sheet', request )
   12.27 +    
   12.28 +        if not currSheet is None:
   12.29 +            currSheet = int( currSheet )
   12.30 +        else:
   12.31 +            currSheet = 0
   12.32 +            
   12.33 +        op = getVar( 'op', request )
   12.34 +        
   12.35 +        if op == 'next':
   12.36 +            currSheet += 1
   12.37 +        elif op == 'prev':
   12.38 +            currSheet -= 1    
   12.39 +            
   12.40 +        self.sheets[ currSheet ]( self.urlWriter ).write_BODY( request )
   12.41 +        
   12.42 +        request.write( "</td></tr><tr><td><table width='100%' border='0' cellspacing='0' cellpadding='0'><tr>" )
   12.43 +        request.write( "<td width='80%'></td><td width='20%' align='center'><p align='center'>" )
   12.44 +	if currSheet > 0:
   12.45 +       		request.write( "<img src='images/previous.png' onclick='doOp( \"prev\" )' onmouseover='update( \"wizText\", \"Previous\" )' onmouseout='update( \"wizText\", \"&nbsp;\" )'>&nbsp;" )
   12.46 +        if currSheet < ( len( self.sheets ) - 1 ):        
   12.47 +        	request.write( "<img src='images/next.png' onclick='doOp( \"next\" )' onmouseover='update( \"wizText\", \"Next\" )' onmouseout='update( \"wizText\", \"&nbsp;\" )'>" )
   12.48 +        request.write( "</p><p align='center'><span id='wizText'></span></p></td></tr></table>" )
   12.49 +        request.write( "</td></tr></table>" )
   12.50 +        
   12.51 +    def op_next( self, request ):
   12.52 +    	pass
   12.53 +        
   12.54 +    def op_prev( self, request ):
   12.55 +    	pass  
   12.56 +        
   12.57 +class Sheet( HTMLBase ):
   12.58 +
   12.59 +    def __init__( self, urlWriter, feilds, title, location ):
   12.60 +        HTMLBase.__init__( self )
   12.61 +        self.urlWriter = urlWriter
   12.62 +        self.feilds = feilds
   12.63 +        self.title = title
   12.64 +        self.location = location
   12.65 +        self.passback = "()"
   12.66 +        
   12.67 +    def parseForm( self, request ):
   12.68 +    	do_not_parse = [ 'mod', 'op', 'sheet' ] 
   12.69 +    
   12.70 +    	passed_back = request.args
   12.71 +        
   12.72 +        temp_passback = passed_back.get( "passback" )
   12.73 +        
   12.74 +        if temp_passback is not None and len( temp_passback ) > 0:
   12.75 +            temp_passback = temp_passback[ len( temp_passback )-1 ]
   12.76 +        else:
   12.77 +            temp_passback = "(passback )"        
   12.78 +        
   12.79 +        last_passback = ssxp2hash( string2sxp( temp_passback ) )
   12.80 +        
   12.81 +        if DEBUG: print last_passback
   12.82 +        
   12.83 +        try: 
   12.84 +            del passed_back[ 'passback' ]
   12.85 +        except:
   12.86 +            pass
   12.87 +        
   12.88 +        for (key, value) in passed_back.items():
   12.89 +            if key not in do_not_parse:
   12.90 +                last_passback[ key ] = value[ len( value ) - 1 ]
   12.91 +                
   12.92 +        self.passback = sxp2string( hash2sxp( last_passback ) ) #store the sxp
   12.93 +        
   12.94 +        if DEBUG: print self.passback
   12.95 +        
   12.96 +        return last_passback #return the hash
   12.97 +        
   12.98 +    def write_BODY( self, request ):
   12.99 +        
  12.100 +   	request.write( "<p>%s</p>" % self.title )
  12.101 +    
  12.102 +    	previous_values = self.parseForm( request ) #get the hash for quick reference
  12.103 +        
  12.104 +    	for (feild, name) in self.feilds:
  12.105 +            value = previous_values.get( feild )
  12.106 +            if value is None:
  12.107 +            	value = ''
  12.108 +            request.write( "<p>%s<input type='text' name='%s' value='%s'></p>" % (name, feild, value) )
  12.109 +        
  12.110 +        request.write( "<input type='hidden' name='passback' value=\"%s\"></p>" % self.passback )
  12.111 +        request.write( "<input type='hidden' name='sheet' value='%s'></p>" % self.location )        
  12.112 +                 
  12.113 +            
  12.114 +    
  12.115 +      
    13.1 --- a/tools/python/xen/sv/Wizzard.py	Wed Jul 28 13:45:22 2004 +0000
    13.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.3 @@ -1,66 +0,0 @@
    13.4 -from xen.sv.util import *
    13.5 -from xen.sv.HTMLBase import HTMLBase
    13.6 -from xen.xend import sxp
    13.7 -
    13.8 -class Wizzard( HTMLBase ):
    13.9 -
   13.10 -    def __init__( self, urlWriter, title, sheets ):
   13.11 -        HTMLBase.__init__( self )
   13.12 -        self.title = title
   13.13 -        self.sheets = sheets
   13.14 -        self.currSheet = 0
   13.15 -        self.urlWriter = urlWriter
   13.16 -        
   13.17 -    def write_MENU( self, request ):
   13.18 -    	request.write( "<p class='small'><a href='%s'>%s</a></p>" % (self.urlWriter( '' ), self.title) ) 
   13.19 -    
   13.20 -    def write_BODY( self, request ):
   13.21 -        
   13.22 -   	request.write( "<table width='100%' border='0' cellspacing='0' cellpadding='0'><tr><td>" )
   13.23 -        request.write( "<p align='center'><u>%s</u></p></td></tr><tr><td>" % self.title )
   13.24 -        
   13.25 -        currSheet = getVar( 'sheet', request )
   13.26 -    
   13.27 -        if not currSheet is None:
   13.28 -        
   13.29 -            self.currSheet = int( currSheet )
   13.30 -            
   13.31 -        self.sheets[ self.currSheet ]( self.urlWriter ).write_BODY( request )
   13.32 -        
   13.33 -        request.write( "</td></tr><tr><td><table width='100%' border='0' cellspacing='0' cellpadding='0'><tr>" )
   13.34 -        request.write( "<td width='80%'></td><td width='20%' align='center'>" )
   13.35 -        request.write( "<p align='center'><img src='images/previous.png' onclick='doOp( \"prev\" )' onmouseover='update( \"wizText\", \"Previous\" )' onmouseout='update( \"wizText\", \"&nbsp;\" )'>&nbsp;" )
   13.36 -        request.write( "<img src='images/next.png' onclick='doOp( \"next\" )' onmouseover='update( \"wizText\", \"Next\" )' onmouseout='update( \"wizText\", \"&nbsp;\" )'></p>" )
   13.37 -        request.write( "<p align='center'><span id='wizText'></span></p></td></tr></table>" )
   13.38 -        request.write( "</td></tr></table>" )
   13.39 -        
   13.40 -class Sheet( HTMLBase ):
   13.41 -
   13.42 -    def __init__( self, urlWriter, feilds, title ):
   13.43 -        HTMLBase.__init__( self )
   13.44 -        self.urlWriter = urlWriter
   13.45 -        self.feilds = feilds
   13.46 -        self.title = title
   13.47 -        
   13.48 -    def parseForm( self, request ):
   13.49 -    	return sxp.toString( request.args )
   13.50 -        
   13.51 -    def write_BODY( self, request ):
   13.52 -   	request.write( "<p>%s</p>" % self.title )
   13.53 -    
   13.54 -    	previous_values = request.args
   13.55 -        
   13.56 -    	for (feild, name) in self.feilds:
   13.57 -            value = sxp.child_value( previous_values, feild )
   13.58 -            if value is None:
   13.59 -            	value = ''
   13.60 -            request.write( "<p>%s<input type='text' name='%s' value='%s'></p>" % (name, feild, value) )
   13.61 -            
   13.62 -    def op_next( self, request ):
   13.63 -    	pass
   13.64 -        
   13.65 -    def op_prev( self, request ):
   13.66 -    	pass        
   13.67 -            
   13.68 -    
   13.69 -      
    14.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    14.2 +++ b/tools/python/xen/sv/params.py	Wed Jul 28 13:48:19 2004 +0000
    14.3 @@ -0,0 +1,3 @@
    14.4 +SV_PORT = 8080
    14.5 +SV_ROOT = "/var/xen/sv/"
    14.6 +PID_FILE = "/var/xen/sv.pid"
    14.7 \ No newline at end of file
    15.1 --- a/tools/python/xen/sv/util.py	Wed Jul 28 13:45:22 2004 +0000
    15.2 +++ b/tools/python/xen/sv/util.py	Wed Jul 28 13:48:19 2004 +0000
    15.3 @@ -18,7 +18,32 @@ def sxp2hash( s ):
    15.4          else:
    15.5              sxphash[ child[0] ] = child[1]
    15.6          
    15.7 -    return sxphash   
    15.8 +    return sxphash  
    15.9 +    
   15.10 +def ssxp2hash( s ):
   15.11 +    sxphash = {}
   15.12 +    
   15.13 +    for i in s:
   15.14 +       if isinstance( i, types.ListType ) and len( i ) > 1:
   15.15 +          sxphash[ i[0] ] = i[1]
   15.16 +    
   15.17 +    return sxphash 
   15.18 +    
   15.19 +def hash2sxp( h ):
   15.20 +    hashsxp = []
   15.21 +    
   15.22 +    for (key, item) in h.items():
   15.23 +    	hashsxp.append( [key, item] )
   15.24 +        
   15.25 +    return hashsxp    
   15.26 +    
   15.27 +def string2sxp( string ):
   15.28 +    pin = sxp.Parser()
   15.29 +    pin.input( string )
   15.30 +    return pin.get_val()    
   15.31 +
   15.32 +def sxp2string( sexp ):
   15.33 +    return sxp.to_string( sexp )    
   15.34      
   15.35  def sxp2prettystring( sxp ):
   15.36      class tmp:
    16.1 --- a/tools/python/xen/util/Brctl.py	Wed Jul 28 13:45:22 2004 +0000
    16.2 +++ b/tools/python/xen/util/Brctl.py	Wed Jul 28 13:48:19 2004 +0000
    16.3 @@ -61,6 +61,7 @@ def bridge_create(bridge, **kwd):
    16.4      if kwd.get('stp', None) is None:
    16.5          kwd['stp'] = 'off'
    16.6      bridge_set(bridge, **kwd)
    16.7 +    cmd(CMD_IFCONFIG, "%s up" % bridge)
    16.8  
    16.9  def bridge_set(bridge, hello=None, fd=None, stp=None):
   16.10      """Set bridge parameters.
    17.1 --- a/tools/python/xen/xend/XendClient.py	Wed Jul 28 13:45:22 2004 +0000
    17.2 +++ b/tools/python/xen/xend/XendClient.py	Wed Jul 28 13:48:19 2004 +0000
    17.3 @@ -510,6 +510,11 @@ class Xend:
    17.4                                'latency' : latency,
    17.5                                'xtratime': xtratime })
    17.6  
    17.7 +    def xend_domain_maxmem_set(self, id, memory):
    17.8 +        return self.xendPost(self.domainurl(id),
    17.9 +                             { 'op'     : 'maxmem_set',
   17.10 +                               'memory' : memory })
   17.11 +
   17.12      def xend_domain_vifs(self, id):
   17.13          return self.xendGet(self.domainurl(id),
   17.14                              { 'op'      : 'vifs' })
   17.15 @@ -565,9 +570,6 @@ class Xend:
   17.16                               {'op'      : 'inject',
   17.17                                'event'   : fileof(sxpr) })
   17.18  
   17.19 -    def xend_dmesg(self):
   17.20 -        return self.xendGet(self.dmesgurl())
   17.21 -
   17.22  def xendmain(srv, asynch, fn, args):
   17.23      if asynch:
   17.24          client = AsynchXendClientProtocol()
    18.1 --- a/tools/python/xen/xend/XendDomain.py	Wed Jul 28 13:45:22 2004 +0000
    18.2 +++ b/tools/python/xen/xend/XendDomain.py	Wed Jul 28 13:48:19 2004 +0000
    18.3 @@ -686,6 +686,17 @@ class XendDomain:
    18.4          dom = int(dom)
    18.5          return xc.shadow_control(dom, op)
    18.6  
    18.7 +    def domain_maxmem_set(self, dom, mem):
    18.8 +        """Set the memory limit for a domain.
    18.9 +
   18.10 +        @param dom: domain
   18.11 +        @param mem: memory limit (in MB)
   18.12 +        @return: 0 on success, -1 on error
   18.13 +        """
   18.14 +        dom = int(dom)
   18.15 +        maxmem = int(mem) * 1024
   18.16 +        return xc.domain_setmaxmem(dom, maxmem_kb = maxmem)
   18.17 +
   18.18  
   18.19  def instance():
   18.20      """Singleton constructor. Use this instead of the class constructor.
    19.1 --- a/tools/python/xen/xend/XendDomainInfo.py	Wed Jul 28 13:45:22 2004 +0000
    19.2 +++ b/tools/python/xen/xend/XendDomainInfo.py	Wed Jul 28 13:48:19 2004 +0000
    19.3 @@ -408,12 +408,13 @@ class XendDomainInfo:
    19.4                  ['memory', self.memory] ]
    19.5  
    19.6          if self.info:
    19.7 -            run   = (self.info['running'] and 'r') or '-'
    19.8 -            block = (self.info['blocked'] and 'b') or '-'
    19.9 -            stop  = (self.info['paused']  and 'p') or '-'
   19.10 -            susp  = (self.info['shutdown'] and 's') or '-'
   19.11 -            crash = (self.info['crashed'] and 'c') or '-'
   19.12 -            state = run + block + stop + susp + crash
   19.13 +            sxpr.append(['maxmem', self.info['maxmem_kb']/1024 ])
   19.14 +            run   = (self.info['running']  and 'r') or '-'
   19.15 +            block = (self.info['blocked']  and 'b') or '-'
   19.16 +            pause = (self.info['paused']   and 'p') or '-'
   19.17 +            shut  = (self.info['shutdown'] and 's') or '-'
   19.18 +            crash = (self.info['crashed']  and 'c') or '-'
   19.19 +            state = run + block + pause + shut + crash
   19.20              sxpr.append(['state', state])
   19.21              if self.info['shutdown']:
   19.22                  reason = shutdown_reason(self.info['shutdown_reason'])
    20.1 --- a/tools/python/xen/xend/server/SrvDomain.py	Wed Jul 28 13:45:22 2004 +0000
    20.2 +++ b/tools/python/xen/xend/server/SrvDomain.py	Wed Jul 28 13:48:19 2004 +0000
    20.3 @@ -151,6 +151,13 @@ class SrvDomain(SrvDir):
    20.4          val = fn(req.args, {'dom': self.dom.id})
    20.5          return val
    20.6  
    20.7 +    def op_maxmem_set(self, op, req):
    20.8 +        fn = FormFn(self.xd.domain_maxmem_set,
    20.9 +                    [['dom', 'int'],
   20.10 +                     ['memory', 'int']])
   20.11 +        val = fn(req.args, {'dom': self.dom.id})
   20.12 +        return val
   20.13 +
   20.14      def op_vifs(self, op, req):
   20.15          return self.xd.domain_vif_ls(self.dom.id)
   20.16  
    21.1 --- a/tools/python/xen/xm/main.py	Wed Jul 28 13:45:22 2004 +0000
    21.2 +++ b/tools/python/xen/xm/main.py	Wed Jul 28 13:48:19 2004 +0000
    21.3 @@ -351,6 +351,22 @@ class ProgPincpu(Prog):
    21.4  
    21.5  xm.prog(ProgPincpu)
    21.6  
    21.7 +class ProgMaxmem(Prog):
    21.8 +    group = 'domain'
    21.9 +    name = 'maxmem'
   21.10 +    info = """Set domain memory limit."""
   21.11 +
   21.12 +    def help(self, args):
   21.13 +        print args[0], "DOM MEMORY"
   21.14 +        print "\nSet the memory limit for domain DOM to MEMORY megabytes."
   21.15 +
   21.16 +    def main(self, args):
   21.17 +        if len(args) != 3: self.err("%s: Invalid argument(s)" % args[0])
   21.18 +        v = map(int, args[1:3])
   21.19 +        server.xend_domain_maxmem_set(*v)
   21.20 +
   21.21 +xm.prog(ProgMaxmem)
   21.22 +
   21.23  class ProgBvt(Prog):
   21.24      group = 'scheduler'
   21.25      name = "bvt"
   21.26 @@ -529,7 +545,7 @@ class ProgDmesg(Prog):
   21.27      info  = """Print Xen boot output."""
   21.28  
   21.29      def main(self, args):
   21.30 -        print server.xend_dmesg()[1]
   21.31 +        print server.xend_node_dmesg()[1]
   21.32  
   21.33  xm.prog(ProgDmesg)
   21.34  
    22.1 --- a/xen/arch/x86/domain.c	Wed Jul 28 13:45:22 2004 +0000
    22.2 +++ b/xen/arch/x86/domain.c	Wed Jul 28 13:48:19 2004 +0000
    22.3 @@ -210,6 +210,11 @@ void machine_halt(void)
    22.4      __machine_halt(NULL);
    22.5  }
    22.6  
    22.7 +void free_perdomain_pt(struct domain *d)
    22.8 +{
    22.9 +    free_xenheap_page((unsigned long)d->mm.perdomain_pt);
   22.10 +}
   22.11 +
   22.12  void arch_do_createdomain(struct domain *d)
   22.13  {
   22.14      d->shared_info = (void *)alloc_xenheap_page();
   22.15 @@ -467,19 +472,19 @@ void domain_relinquish_memory(struct dom
   22.16  
   22.17      /* Relinquish Xen-heap pages. Currently this can only be 'shared_info'. */
   22.18      page = virt_to_page(d->shared_info);
   22.19 -    if ( test_and_clear_bit(_PGC_allocated, &page->count_and_flags) )
   22.20 +    if ( test_and_clear_bit(_PGC_allocated, &page->u.inuse.count_info) )
   22.21          put_page(page);
   22.22  
   22.23      /* Relinquish all pages on the domain's allocation list. */
   22.24 -    spin_lock_recursive(&d->page_alloc_lock); /* may enter free_domain_page */
   22.25 +    spin_lock_recursive(&d->page_alloc_lock); /* may enter free_domheap_page */
   22.26      list_for_each_safe ( ent, tmp, &d->page_list )
   22.27      {
   22.28          page = list_entry(ent, struct pfn_info, list);
   22.29  
   22.30 -        if ( test_and_clear_bit(_PGC_guest_pinned, &page->count_and_flags) )
   22.31 +        if ( test_and_clear_bit(_PGC_guest_pinned, &page->u.inuse.count_info) )
   22.32              put_page_and_type(page);
   22.33  
   22.34 -        if ( test_and_clear_bit(_PGC_allocated, &page->count_and_flags) )
   22.35 +        if ( test_and_clear_bit(_PGC_allocated, &page->u.inuse.count_info) )
   22.36              put_page(page);
   22.37  
   22.38          /*
   22.39 @@ -488,13 +493,13 @@ void domain_relinquish_memory(struct dom
   22.40           * are not shared across domains and this domain is now dead. Thus base
   22.41           * tables are not in use so a non-zero count means circular reference.
   22.42           */
   22.43 -        y = page->type_and_flags;
   22.44 +        y = page->u.inuse.type_info;
   22.45          do {
   22.46              x = y;
   22.47              if ( likely((x & (PGT_type_mask|PGT_validated)) != 
   22.48                          (PGT_base_page_table|PGT_validated)) )
   22.49                  break;
   22.50 -            y = cmpxchg(&page->type_and_flags, x, x & ~PGT_validated);
   22.51 +            y = cmpxchg(&page->u.inuse.type_info, x, x & ~PGT_validated);
   22.52              if ( likely(y == x) )
   22.53                  free_page_type(page, PGT_base_page_table);
   22.54          }
   22.55 @@ -654,9 +659,9 @@ int construct_dom0(struct domain *p,
   22.56            mfn++ )
   22.57      {
   22.58          page = &frame_table[mfn];
   22.59 -        page->u.domain        = p;
   22.60 -        page->type_and_flags  = 0;
   22.61 -        page->count_and_flags = PGC_allocated | 1;
   22.62 +        page->u.inuse.domain        = p;
   22.63 +        page->u.inuse.type_info  = 0;
   22.64 +        page->u.inuse.count_info = PGC_allocated | 1;
   22.65          list_add_tail(&page->list, &p->page_list);
   22.66          p->tot_pages++; p->max_pages++;
   22.67      }
   22.68 @@ -701,7 +706,7 @@ int construct_dom0(struct domain *p,
   22.69          *l1tab++ = mk_l1_pgentry((mfn << PAGE_SHIFT) | L1_PROT);
   22.70          
   22.71          page = &frame_table[mfn];
   22.72 -        set_bit(_PGC_tlb_flush_on_type_change, &page->count_and_flags);
   22.73 +        set_bit(_PGC_tlb_flush_on_type_change, &page->u.inuse.count_info);
   22.74          if ( !get_page_and_type(page, p, PGT_writeable_page) )
   22.75              BUG();
   22.76  
   22.77 @@ -719,18 +724,18 @@ int construct_dom0(struct domain *p,
   22.78          page = &frame_table[l1_pgentry_to_pagenr(*l1tab)];
   22.79          if ( count == 0 )
   22.80          {
   22.81 -            page->type_and_flags &= ~PGT_type_mask;
   22.82 -            page->type_and_flags |= PGT_l2_page_table;
   22.83 +            page->u.inuse.type_info &= ~PGT_type_mask;
   22.84 +            page->u.inuse.type_info |= PGT_l2_page_table;
   22.85              get_page(page, p); /* an extra ref because of readable mapping */
   22.86              /* Get another ref to L2 page so that it can be pinned. */
   22.87              if ( !get_page_and_type(page, p, PGT_l2_page_table) )
   22.88                  BUG();
   22.89 -            set_bit(_PGC_guest_pinned, &page->count_and_flags);
   22.90 +            set_bit(_PGC_guest_pinned, &page->u.inuse.count_info);
   22.91          }
   22.92          else
   22.93          {
   22.94 -            page->type_and_flags &= ~PGT_type_mask;
   22.95 -            page->type_and_flags |= PGT_l1_page_table;
   22.96 +            page->u.inuse.type_info &= ~PGT_type_mask;
   22.97 +            page->u.inuse.type_info |= PGT_l1_page_table;
   22.98              get_page(page, p); /* an extra ref because of readable mapping */
   22.99          }
  22.100          l1tab++;
    23.1 --- a/xen/arch/x86/memory.c	Wed Jul 28 13:45:22 2004 +0000
    23.2 +++ b/xen/arch/x86/memory.c	Wed Jul 28 13:48:19 2004 +0000
    23.3 @@ -245,7 +245,7 @@ static int get_page_and_type_from_pagenr
    23.4      if ( unlikely(!get_page_type(page, type)) )
    23.5      {
    23.6          MEM_LOG("Bad page type for pfn %08lx (%08x)", 
    23.7 -                page_nr, page->type_and_flags);
    23.8 +                page_nr, page->u.inuse.type_info);
    23.9          put_page(page);
   23.10          return 0;
   23.11      }
   23.12 @@ -288,7 +288,7 @@ static int get_linear_pagetable(l2_pgent
   23.13           * If so, atomically increment the count (checking for overflow).
   23.14           */
   23.15          page = &frame_table[l2_pgentry_to_pagenr(l2e)];
   23.16 -        y = page->type_and_flags;
   23.17 +        y = page->u.inuse.type_info;
   23.18          do {
   23.19              x = y;
   23.20              if ( unlikely((x & PGT_count_mask) == PGT_count_mask) ||
   23.21 @@ -299,7 +299,7 @@ static int get_linear_pagetable(l2_pgent
   23.22                  return 0;
   23.23              }
   23.24          }
   23.25 -        while ( (y = cmpxchg(&page->type_and_flags, x, x + 1)) != x );
   23.26 +        while ( (y = cmpxchg(&page->u.inuse.type_info, x, x + 1)) != x );
   23.27      }
   23.28  
   23.29      return 1;
   23.30 @@ -339,7 +339,7 @@ static int get_page_from_l1e(l1_pgentry_
   23.31              pfn, PGT_writeable_page, GPS)) )
   23.32              return 0;
   23.33          set_bit(_PGC_tlb_flush_on_type_change, 
   23.34 -                &frame_table[pfn].count_and_flags);
   23.35 +                &frame_table[pfn].u.inuse.count_info);
   23.36          return 1;
   23.37      }
   23.38  
   23.39 @@ -383,10 +383,10 @@ static void put_page_from_l1e(l1_pgentry
   23.40      else
   23.41      {
   23.42          /* We expect this is rare so we blow the entire shadow LDT. */
   23.43 -        if ( unlikely(((page->type_and_flags & PGT_type_mask) == 
   23.44 +        if ( unlikely(((page->u.inuse.type_info & PGT_type_mask) == 
   23.45                         PGT_ldt_page)) &&
   23.46 -             unlikely(((page->type_and_flags & PGT_count_mask) != 0)) )
   23.47 -            invalidate_shadow_ldt(page->u.domain);
   23.48 +             unlikely(((page->u.inuse.type_info & PGT_count_mask) != 0)) )
   23.49 +            invalidate_shadow_ldt(page->u.inuse.domain);
   23.50          put_page(page);
   23.51      }
   23.52  }
   23.53 @@ -424,7 +424,7 @@ static int alloc_l2_table(struct pfn_inf
   23.54      pl2e[LINEAR_PT_VIRT_START >> L2_PAGETABLE_SHIFT] =
   23.55          mk_l2_pgentry((page_nr << PAGE_SHIFT) | __PAGE_HYPERVISOR);
   23.56      pl2e[PERDOMAIN_VIRT_START >> L2_PAGETABLE_SHIFT] =
   23.57 -        mk_l2_pgentry(__pa(page->u.domain->mm.perdomain_pt) | 
   23.58 +        mk_l2_pgentry(__pa(page->u.inuse.domain->mm.perdomain_pt) | 
   23.59                        __PAGE_HYPERVISOR);
   23.60  #endif
   23.61  
   23.62 @@ -617,9 +617,9 @@ static int mod_l1_entry(l1_pgentry_t *pl
   23.63  int alloc_page_type(struct pfn_info *page, unsigned int type)
   23.64  {
   23.65      if ( unlikely(test_and_clear_bit(_PGC_tlb_flush_on_type_change, 
   23.66 -                                     &page->count_and_flags)) )
   23.67 +                                     &page->u.inuse.count_info)) )
   23.68      {
   23.69 -        struct domain *p = page->u.domain;
   23.70 +        struct domain *p = page->u.inuse.domain;
   23.71          if ( unlikely(NEED_FLUSH(tlbflush_time[p->processor],
   23.72                                   page->tlbflush_timestamp)) )
   23.73          {
   23.74 @@ -713,7 +713,7 @@ static int do_extended_command(unsigned 
   23.75          }
   23.76  
   23.77          if ( unlikely(test_and_set_bit(_PGC_guest_pinned, 
   23.78 -                                       &page->count_and_flags)) )
   23.79 +                                       &page->u.inuse.count_info)) )
   23.80          {
   23.81              MEM_LOG("Pfn %08lx already pinned", pfn);
   23.82              put_page_and_type(page);
   23.83 @@ -727,10 +727,10 @@ static int do_extended_command(unsigned 
   23.84          if ( unlikely(!(okay = get_page_from_pagenr(pfn, PTS))) )
   23.85          {
   23.86              MEM_LOG("Page %08lx bad domain (dom=%p)",
   23.87 -                    ptr, page->u.domain);
   23.88 +                    ptr, page->u.inuse.domain);
   23.89          }
   23.90          else if ( likely(test_and_clear_bit(_PGC_guest_pinned, 
   23.91 -                                            &page->count_and_flags)) )
   23.92 +                                            &page->u.inuse.count_info)) )
   23.93          {
   23.94              put_page_and_type(page);
   23.95              put_page(page);
   23.96 @@ -874,8 +874,8 @@ static int do_extended_command(unsigned 
   23.97           * benign reference to the page (PGC_allocated). If that reference
   23.98           * disappears then the deallocation routine will safely spin.
   23.99           */
  23.100 -        nd = page->u.domain;
  23.101 -        y  = page->count_and_flags;
  23.102 +        nd = page->u.inuse.domain;
  23.103 +        y  = page->u.inuse.count_info;
  23.104          do {
  23.105              x = y;
  23.106              if ( unlikely((x & (PGC_count_mask|PGC_allocated)) != 
  23.107 @@ -884,14 +884,14 @@ static int do_extended_command(unsigned 
  23.108              {
  23.109                  MEM_LOG("Bad page values %08lx: ed=%p(%u), sd=%p,"
  23.110                          " caf=%08x, taf=%08x\n", page_to_pfn(page),
  23.111 -                        d, d->domain, nd, x, page->type_and_flags);
  23.112 +                        d, d->domain, nd, x, page->u.inuse.type_info);
  23.113                  okay = 0;
  23.114                  goto reassign_fail;
  23.115              }
  23.116              __asm__ __volatile__(
  23.117                  LOCK_PREFIX "cmpxchg8b %3"
  23.118                  : "=a" (nd), "=d" (y), "=b" (e),
  23.119 -                "=m" (*(volatile u64 *)(&page->u.domain))
  23.120 +                "=m" (*(volatile u64 *)(&page->u.inuse.domain))
  23.121                  : "0" (d), "1" (x), "b" (e), "c" (x) );
  23.122          } 
  23.123          while ( unlikely(nd != d) || unlikely(y != x) );
  23.124 @@ -985,7 +985,7 @@ int do_mmu_update(mmu_update_t *ureqs, i
  23.125              }
  23.126  
  23.127              page = &frame_table[pfn];
  23.128 -            switch ( (page->type_and_flags & PGT_type_mask) )
  23.129 +            switch ( (page->u.inuse.type_info & PGT_type_mask) )
  23.130              {
  23.131              case PGT_l1_page_table: 
  23.132                  if ( likely(get_page_type(page, PGT_l1_page_table)) )
    24.1 --- a/xen/arch/x86/shadow.c	Wed Jul 28 13:45:22 2004 +0000
    24.2 +++ b/xen/arch/x86/shadow.c	Wed Jul 28 13:48:19 2004 +0000
    24.3 @@ -64,11 +64,10 @@ interrupts enabled. Nothing can go wrong
    24.4  
    24.5  **/
    24.6  
    24.7 -static inline void free_shadow_page( struct mm_struct *m, 
    24.8 -                                     struct pfn_info *pfn_info )
    24.9 +static inline void free_shadow_page(struct mm_struct *m, 
   24.10 +                                    struct pfn_info *page)
   24.11  {
   24.12 -    unsigned long flags;
   24.13 -    unsigned long type = pfn_info->type_and_flags & PGT_type_mask;
   24.14 +    unsigned long type = page->u.inuse.type_info & PGT_type_mask;
   24.15  
   24.16      m->shadow_page_count--;
   24.17  
   24.18 @@ -77,14 +76,9 @@ static inline void free_shadow_page( str
   24.19      else if (type == PGT_l2_page_table)
   24.20          perfc_decr(shadow_l2_pages);
   24.21      else printk("Free shadow weird page type pfn=%08x type=%08x\n",
   24.22 -                frame_table-pfn_info, pfn_info->type_and_flags);
   24.23 +                frame_table-page, page->u.inuse.type_info);
   24.24      
   24.25 -    pfn_info->type_and_flags = 0;
   24.26 -
   24.27 -    spin_lock_irqsave(&free_list_lock, flags);
   24.28 -    list_add(&pfn_info->list, &free_list);
   24.29 -    free_pfns++;
   24.30 -    spin_unlock_irqrestore(&free_list_lock, flags);
   24.31 +    free_domheap_page(page);
   24.32  }
   24.33  
   24.34  static void __free_shadow_table( struct mm_struct *m )
   24.35 @@ -147,7 +141,7 @@ static inline int shadow_page_op( struct
   24.36      {
   24.37  	case TABLE_OP_ZERO_L2:
   24.38  	{
   24.39 -		if ( (spfn_info->type_and_flags & PGT_type_mask) == 
   24.40 +		if ( (spfn_info->u.inuse.type_info & PGT_type_mask) == 
   24.41               PGT_l2_page_table )
   24.42  		{
   24.43  			unsigned long * spl1e = map_domain_mem( spfn<<PAGE_SHIFT );
   24.44 @@ -161,7 +155,7 @@ static inline int shadow_page_op( struct
   24.45  	
   24.46  	case TABLE_OP_ZERO_L1:
   24.47  	{
   24.48 -		if ( (spfn_info->type_and_flags & PGT_type_mask) == 
   24.49 +		if ( (spfn_info->u.inuse.type_info & PGT_type_mask) == 
   24.50               PGT_l1_page_table )
   24.51  		{
   24.52  			unsigned long * spl1e = map_domain_mem( spfn<<PAGE_SHIFT );
   24.53 @@ -173,7 +167,7 @@ static inline int shadow_page_op( struct
   24.54  
   24.55  	case TABLE_OP_FREE_L1:
   24.56  	{
   24.57 -		if ( (spfn_info->type_and_flags & PGT_type_mask) == 
   24.58 +		if ( (spfn_info->u.inuse.type_info & PGT_type_mask) == 
   24.59               PGT_l1_page_table )
   24.60  		{
   24.61  			// lock is already held
   24.62 @@ -518,7 +512,7 @@ int shadow_mode_control(struct domain *d
   24.63  static inline struct pfn_info *alloc_shadow_page(struct mm_struct *m)
   24.64  {
   24.65      m->shadow_page_count++;
   24.66 -    return alloc_domain_page(NULL);
   24.67 +    return alloc_domheap_page(NULL);
   24.68  }
   24.69  
   24.70  void unshadow_table( unsigned long gpfn, unsigned int type )
   24.71 @@ -564,7 +558,7 @@ unsigned long shadow_l2_table(
   24.72  
   24.73      ASSERT( spfn_info ); // XXX deal with failure later e.g. blow cache
   24.74  
   24.75 -    spfn_info->type_and_flags = PGT_l2_page_table;
   24.76 +    spfn_info->u.inuse.type_info = PGT_l2_page_table;
   24.77      perfc_incr(shadow_l2_pages);
   24.78  
   24.79      spfn = (unsigned long) (spfn_info - frame_table);
   24.80 @@ -585,7 +579,7 @@ unsigned long shadow_l2_table(
   24.81      spl2e[SH_LINEAR_PT_VIRT_START >> L2_PAGETABLE_SHIFT] =
   24.82          mk_l2_pgentry((spfn << PAGE_SHIFT) | __PAGE_HYPERVISOR);
   24.83      spl2e[PERDOMAIN_VIRT_START >> L2_PAGETABLE_SHIFT] =
   24.84 -        mk_l2_pgentry(__pa(frame_table[gpfn].u.domain->mm.perdomain_pt) | 
   24.85 +        mk_l2_pgentry(__pa(frame_table[gpfn].u.inuse.domain->mm.perdomain_pt) | 
   24.86                        __PAGE_HYPERVISOR);
   24.87  #endif
   24.88  
   24.89 @@ -728,7 +722,7 @@ int shadow_fault( unsigned long va, long
   24.90              unsigned long *gpl1e, *spl1e;
   24.91              int i;
   24.92              sl1pfn_info = alloc_shadow_page( &current->mm ); 
   24.93 -            sl1pfn_info->type_and_flags = PGT_l1_page_table;
   24.94 +            sl1pfn_info->u.inuse.type_info = PGT_l1_page_table;
   24.95  			
   24.96              sl1pfn = sl1pfn_info - frame_table;
   24.97  
   24.98 @@ -1017,7 +1011,7 @@ int check_pagetable( struct mm_struct *m
   24.99              );
  24.100  
  24.101      if ( (l2_pgentry_val(spl2e[PERDOMAIN_VIRT_START >> L2_PAGETABLE_SHIFT]) !=
  24.102 -          ((__pa(frame_table[gpfn].u.domain->mm.perdomain_pt) | __PAGE_HYPERVISOR))) )
  24.103 +          ((__pa(frame_table[gpfn].u.inuse.domain->mm.perdomain_pt) | __PAGE_HYPERVISOR))) )
  24.104          FAILPT("hypervisor per-domain map inconsistent");
  24.105  
  24.106  
    25.1 --- a/xen/arch/x86/x86_32/mm.c	Wed Jul 28 13:45:22 2004 +0000
    25.2 +++ b/xen/arch/x86/x86_32/mm.c	Wed Jul 28 13:48:19 2004 +0000
    25.3 @@ -338,7 +338,7 @@ long do_update_descriptor(
    25.4          return -EINVAL;
    25.5  
    25.6      /* Check if the given frame is in use in an unsafe context. */
    25.7 -    switch ( page->type_and_flags & PGT_type_mask )
    25.8 +    switch ( page->u.inuse.type_info & PGT_type_mask )
    25.9      {
   25.10      case PGT_gdt_page:
   25.11          /* Disallow updates of Xen-reserved descriptors in the current GDT. */
    26.1 --- a/xen/common/dom0_ops.c	Wed Jul 28 13:45:22 2004 +0000
    26.2 +++ b/xen/common/dom0_ops.c	Wed Jul 28 13:48:19 2004 +0000
    26.3 @@ -29,16 +29,16 @@ extern void arch_getdomaininfo_ctxt(stru
    26.4  
    26.5  static inline int is_free_domid(domid_t dom)
    26.6  {
    26.7 -    struct domain  *d;
    26.8 +    struct domain *d;
    26.9 +
   26.10 +    if ( dom >= DOMID_SELF )
   26.11 +        return 0;
   26.12  
   26.13 -    if (dom >= DOMID_SELF) return 0;
   26.14 -    d = find_domain_by_id(dom);
   26.15 -    if (d == NULL) {
   26.16 +    if ( (d = find_domain_by_id(dom)) == NULL )
   26.17          return 1;
   26.18 -    } else {
   26.19 -        put_domain(d);
   26.20 -        return 0;
   26.21 -    }
   26.22 +
   26.23 +    put_domain(d);
   26.24 +    return 0;
   26.25  }
   26.26  
   26.27  /** Allocate a free domain id. We try to reuse domain ids in a fairly low range,
   26.28 @@ -52,73 +52,43 @@ static int allocate_domid(domid_t *pdom)
   26.29      static domid_t curdom = 0;
   26.30      static domid_t topdom = 101;
   26.31      int err = 0;
   26.32 -    domid_t cur, dom, top;
   26.33 +    domid_t dom;
   26.34 +
   26.35 +    spin_lock(&domid_lock);
   26.36  
   26.37      /* Try to use a domain id in the range 0..topdom, starting at curdom. */
   26.38 -    spin_lock(&domid_lock);
   26.39 -    cur = curdom;
   26.40 -    dom = curdom;
   26.41 -    top = topdom;
   26.42 -    spin_unlock(&domid_lock);
   26.43 -    do {
   26.44 -        ++dom;
   26.45 -        if (dom == top) {
   26.46 +    for ( dom = curdom + 1; dom != curdom; dom++ )
   26.47 +    {
   26.48 +        if ( dom == topdom )
   26.49              dom = 1;
   26.50 -        }
   26.51 -        if (is_free_domid(dom)) goto exit;
   26.52 -    } while (dom != cur);
   26.53 +        if ( is_free_domid(dom) )
   26.54 +            goto exit;
   26.55 +    }
   26.56 +
   26.57      /* Couldn't find a free domain id in 0..topdom, try higher. */
   26.58 -    for (dom = top; dom < DOMID_SELF; dom++) {
   26.59 -        if(is_free_domid(dom)) goto exit;
   26.60 +    for ( dom = topdom; dom < DOMID_SELF; dom++ )
   26.61 +    {
   26.62 +        if ( is_free_domid(dom) )
   26.63 +        {
   26.64 +            topdom = dom + 1;
   26.65 +            goto exit;
   26.66 +        }
   26.67      }
   26.68 +
   26.69      /* No free domain ids. */
   26.70      err = -ENOMEM;
   26.71 +
   26.72    exit:
   26.73 -    if (err == 0) {
   26.74 -        spin_lock(&domid_lock);
   26.75 +    if ( err == 0 )
   26.76 +    {
   26.77          curdom = dom;
   26.78 -        if (dom >= topdom) {
   26.79 -            topdom = dom + 1;
   26.80 -        }
   26.81 -        spin_unlock(&domid_lock);
   26.82          *pdom = dom;
   26.83      }
   26.84 +
   26.85 +    spin_unlock(&domid_lock);
   26.86      return err;
   26.87  }
   26.88  
   26.89 -#if 0
   26.90 -        struct domain    *d;
   26.91 -        static domid_t    domnr = 0;
   26.92 -        static spinlock_t domnr_lock = SPIN_LOCK_UNLOCKED;
   26.93 -        unsigned int      pro;
   26.94 -        domid_t           dom;
   26.95 -
   26.96 -        ret = -ENOMEM;
   26.97 -
   26.98 -        if(op->u.createdomain.domain > 0){
   26.99 -            d = find_domain_by_id(dom);
  26.100 -            if(d){
  26.101 -                put_domain(d);
  26.102 -                ret = -EINVAL;
  26.103 -                break;
  26.104 -            }
  26.105 -        } else {
  26.106 -            /* Search for an unused domain identifier. */
  26.107 -            for ( ; ; )
  26.108 -            {
  26.109 -                spin_lock(&domnr_lock);
  26.110 -                /* Wrap the roving counter when we reach first special value. */
  26.111 -                if ( (dom = ++domnr) == DOMID_SELF )
  26.112 -                    dom = domnr = 1;
  26.113 -                spin_unlock(&domnr_lock);
  26.114 -                
  26.115 -                if ( (d = find_domain_by_id(dom)) == NULL )
  26.116 -                    break;
  26.117 -                put_domain(d);
  26.118 -             }
  26.119 -        }
  26.120 -#endif
  26.121 -
  26.122  long do_dom0_op(dom0_op_t *u_dom0_op)
  26.123  {
  26.124      long ret = 0;
  26.125 @@ -196,30 +166,23 @@ long do_dom0_op(dom0_op_t *u_dom0_op)
  26.126          unsigned int      pro;
  26.127          domid_t           dom;
  26.128  
  26.129 -        ret = -ENOMEM;
  26.130 -
  26.131          dom = op->u.createdomain.domain;
  26.132 -        if ( 0 < dom && dom < DOMID_SELF )
  26.133 +        if ( (dom > 0) && (dom < DOMID_SELF) )
  26.134          {
  26.135 +            ret = -EINVAL;
  26.136              if ( !is_free_domid(dom) )
  26.137 -            {
  26.138 -                ret = -EINVAL;
  26.139                  break;
  26.140 -            }
  26.141          }
  26.142 -        else
  26.143 -        {
  26.144 -            ret = allocate_domid(&dom);
  26.145 -            if ( ret ) break;
  26.146 -        }
  26.147 +        else if ( (ret = allocate_domid(&dom)) != 0 )
  26.148 +            break;
  26.149  
  26.150          if ( op->u.createdomain.cpu == -1 )
  26.151              pro = (unsigned int)dom % smp_num_cpus;
  26.152          else
  26.153              pro = op->u.createdomain.cpu % smp_num_cpus;
  26.154  
  26.155 -        d = do_createdomain(dom, pro);
  26.156 -        if ( d == NULL ) 
  26.157 +        ret = -ENOMEM;
  26.158 +        if ( (d = do_createdomain(dom, pro)) == NULL )
  26.159              break;
  26.160  
  26.161          if ( op->u.createdomain.name[0] )
  26.162 @@ -442,9 +405,9 @@ long do_dom0_op(dom0_op_t *u_dom0_op)
  26.163  
  26.164              op->u.getpageframeinfo.type = NOTAB;
  26.165  
  26.166 -            if ( (page->type_and_flags & PGT_count_mask) != 0 )
  26.167 +            if ( (page->u.inuse.type_info & PGT_count_mask) != 0 )
  26.168              {
  26.169 -                switch ( page->type_and_flags & PGT_type_mask )
  26.170 +                switch ( page->u.inuse.type_info & PGT_type_mask )
  26.171                  {
  26.172                  case PGT_l1_page_table:
  26.173                      op->u.getpageframeinfo.type = L1TAB;
  26.174 @@ -527,7 +490,7 @@ long do_dom0_op(dom0_op_t *u_dom0_op)
  26.175          pi->ht_per_core = ht;
  26.176          pi->cores       = smp_num_cpus / pi->ht_per_core;
  26.177          pi->total_pages = max_page;
  26.178 -        pi->free_pages  = free_pfns;
  26.179 +        pi->free_pages  = avail_domheap_pages();
  26.180          pi->cpu_khz     = cpu_khz;
  26.181  
  26.182          copy_to_user(u_dom0_op, op, sizeof(*op));
  26.183 @@ -645,7 +608,7 @@ long do_dom0_op(dom0_op_t *u_dom0_op)
  26.184                  if ( likely(get_page(page, d)) )
  26.185                  {
  26.186                      unsigned long type = 0;
  26.187 -                    switch( page->type_and_flags & PGT_type_mask )
  26.188 +                    switch( page->u.inuse.type_info & PGT_type_mask )
  26.189                      {
  26.190                      case PGT_l1_page_table:
  26.191                          type = L1TAB;
    27.1 --- a/xen/common/dom_mem_ops.c	Wed Jul 28 13:45:22 2004 +0000
    27.2 +++ b/xen/common/dom_mem_ops.c	Wed Jul 28 13:48:19 2004 +0000
    27.3 @@ -22,20 +22,9 @@ static long alloc_dom_mem(struct domain 
    27.4      struct pfn_info *page;
    27.5      unsigned long    i;
    27.6  
    27.7 -    /* Leave some slack pages; e.g., for the network. */
    27.8 -    if ( unlikely(free_pfns < (nr_pages + (SLACK_DOMAIN_MEM_KILOBYTES >> 
    27.9 -                                           (PAGE_SHIFT-10)))) )
   27.10 -    {
   27.11 -        DPRINTK("Not enough slack: %u %u\n",
   27.12 -                free_pfns,
   27.13 -                SLACK_DOMAIN_MEM_KILOBYTES >> (PAGE_SHIFT-10));
   27.14 -        return 0;
   27.15 -    }
   27.16 -
   27.17      for ( i = 0; i < nr_pages; i++ )
   27.18      {
   27.19 -        /* NB. 'alloc_domain_page' does limit-checking on pages per domain. */
   27.20 -        if ( unlikely((page = alloc_domain_page(d)) == NULL) )
   27.21 +        if ( unlikely((page = alloc_domheap_page(d)) == NULL) )
   27.22          {
   27.23              DPRINTK("Could not allocate a frame\n");
   27.24              break;
   27.25 @@ -78,10 +67,10 @@ static long free_dom_mem(struct domain *
   27.26              break;
   27.27          }
   27.28  
   27.29 -        if ( test_and_clear_bit(_PGC_guest_pinned, &page->count_and_flags) )
   27.30 +        if ( test_and_clear_bit(_PGC_guest_pinned, &page->u.inuse.count_info) )
   27.31              put_page_and_type(page);
   27.32  
   27.33 -        if ( test_and_clear_bit(_PGC_allocated, &page->count_and_flags) )
   27.34 +        if ( test_and_clear_bit(_PGC_allocated, &page->u.inuse.count_info) )
   27.35              put_page(page);
   27.36  
   27.37          put_page(page);
    28.1 --- a/xen/common/domain.c	Wed Jul 28 13:45:22 2004 +0000
    28.2 +++ b/xen/common/domain.c	Wed Jul 28 13:48:19 2004 +0000
    28.3 @@ -15,7 +15,6 @@
    28.4  #include <xen/console.h>
    28.5  #include <asm/shadow.h>
    28.6  #include <hypervisor-ifs/dom0_ops.h>
    28.7 -#include <asm/hardirq.h>
    28.8  #include <asm/domain_page.h>
    28.9  
   28.10  /* Both these structures are protected by the tasklist_lock. */
   28.11 @@ -194,111 +193,6 @@ void domain_shutdown(u8 reason)
   28.12      __enter_scheduler();
   28.13  }
   28.14  
   28.15 -struct pfn_info *alloc_domain_page(struct domain *d)
   28.16 -{
   28.17 -    struct pfn_info *page = NULL;
   28.18 -    unsigned long flags, mask, pfn_stamp, cpu_stamp;
   28.19 -    int i;
   28.20 -
   28.21 -    ASSERT(!in_irq());
   28.22 -
   28.23 -    spin_lock_irqsave(&free_list_lock, flags);
   28.24 -    if ( likely(!list_empty(&free_list)) )
   28.25 -    {
   28.26 -        page = list_entry(free_list.next, struct pfn_info, list);
   28.27 -        list_del(&page->list);
   28.28 -        free_pfns--;
   28.29 -    }
   28.30 -    spin_unlock_irqrestore(&free_list_lock, flags);
   28.31 -
   28.32 -    if ( unlikely(page == NULL) )
   28.33 -        return NULL;
   28.34 -
   28.35 -    if ( (mask = page->u.cpu_mask) != 0 )
   28.36 -    {
   28.37 -        pfn_stamp = page->tlbflush_timestamp;
   28.38 -        for ( i = 0; (mask != 0) && (i < smp_num_cpus); i++ )
   28.39 -        {
   28.40 -            if ( mask & (1<<i) )
   28.41 -            {
   28.42 -                cpu_stamp = tlbflush_time[i];
   28.43 -                if ( !NEED_FLUSH(cpu_stamp, pfn_stamp) )
   28.44 -                    mask &= ~(1<<i);
   28.45 -            }
   28.46 -        }
   28.47 -
   28.48 -        if ( unlikely(mask != 0) )
   28.49 -        {
   28.50 -            flush_tlb_mask(mask);
   28.51 -            perfc_incrc(need_flush_tlb_flush);
   28.52 -        }
   28.53 -    }
   28.54 -
   28.55 -    page->u.domain = d;
   28.56 -    page->type_and_flags = 0;
   28.57 -    if ( d != NULL )
   28.58 -    {
   28.59 -        wmb(); /* Domain pointer must be visible before updating refcnt. */
   28.60 -        spin_lock(&d->page_alloc_lock);
   28.61 -        if ( unlikely(d->tot_pages >= d->max_pages) )
   28.62 -        {
   28.63 -            DPRINTK("Over-allocation for domain %u: %u >= %u\n",
   28.64 -                    d->domain, d->tot_pages, d->max_pages);
   28.65 -            spin_unlock(&d->page_alloc_lock);
   28.66 -            goto free_and_exit;
   28.67 -        }
   28.68 -        list_add_tail(&page->list, &d->page_list);
   28.69 -        page->count_and_flags = PGC_allocated | 1;
   28.70 -        if ( unlikely(d->tot_pages++ == 0) )
   28.71 -            get_domain(d);
   28.72 -        spin_unlock(&d->page_alloc_lock);
   28.73 -    }
   28.74 -
   28.75 -    return page;
   28.76 -
   28.77 - free_and_exit:
   28.78 -    spin_lock_irqsave(&free_list_lock, flags);
   28.79 -    list_add(&page->list, &free_list);
   28.80 -    free_pfns++;
   28.81 -    spin_unlock_irqrestore(&free_list_lock, flags);
   28.82 -    return NULL;
   28.83 -}
   28.84 -
   28.85 -void free_domain_page(struct pfn_info *page)
   28.86 -{
   28.87 -    unsigned long  flags;
   28.88 -    int            drop_dom_ref;
   28.89 -    struct domain *d = page->u.domain;
   28.90 -
   28.91 -    if ( unlikely(IS_XEN_HEAP_FRAME(page)) )
   28.92 -    {
   28.93 -        spin_lock_recursive(&d->page_alloc_lock);
   28.94 -        drop_dom_ref = (--d->xenheap_pages == 0);
   28.95 -        spin_unlock_recursive(&d->page_alloc_lock);
   28.96 -    }
   28.97 -    else
   28.98 -    {
   28.99 -        page->tlbflush_timestamp = tlbflush_clock;
  28.100 -        page->u.cpu_mask = 1 << d->processor;
  28.101 -        
  28.102 -        /* NB. May recursively lock from domain_relinquish_memory(). */
  28.103 -        spin_lock_recursive(&d->page_alloc_lock);
  28.104 -        list_del(&page->list);
  28.105 -        drop_dom_ref = (--d->tot_pages == 0);
  28.106 -        spin_unlock_recursive(&d->page_alloc_lock);
  28.107 -
  28.108 -        page->count_and_flags = 0;
  28.109 -        
  28.110 -        spin_lock_irqsave(&free_list_lock, flags);
  28.111 -        list_add(&page->list, &free_list);
  28.112 -        free_pfns++;
  28.113 -        spin_unlock_irqrestore(&free_list_lock, flags);
  28.114 -    }
  28.115 -
  28.116 -    if ( drop_dom_ref )
  28.117 -        put_domain(d);
  28.118 -}
  28.119 -
  28.120  unsigned int alloc_new_dom_mem(struct domain *d, unsigned int kbytes)
  28.121  {
  28.122      unsigned int alloc_pfns, nr_pages;
  28.123 @@ -310,9 +204,7 @@ unsigned int alloc_new_dom_mem(struct do
  28.124      /* Grow the allocation if necessary. */
  28.125      for ( alloc_pfns = d->tot_pages; alloc_pfns < nr_pages; alloc_pfns++ )
  28.126      {
  28.127 -        if ( unlikely((page=alloc_domain_page(d)) == NULL) ||
  28.128 -             unlikely(free_pfns < (SLACK_DOMAIN_MEM_KILOBYTES >> 
  28.129 -                                   (PAGE_SHIFT-10))) )
  28.130 +        if ( unlikely((page = alloc_domheap_page(d)) == NULL) )
  28.131          {
  28.132              domain_relinquish_memory(d);
  28.133              return -ENOMEM;
    29.1 --- a/xen/common/event_channel.c	Wed Jul 28 13:45:22 2004 +0000
    29.2 +++ b/xen/common/event_channel.c	Wed Jul 28 13:48:19 2004 +0000
    29.3 @@ -197,7 +197,6 @@ static long evtchn_bind_pirq(evtchn_bind
    29.4      if ( rc != 0 )
    29.5      {
    29.6          d->pirq_to_evtchn[pirq] = 0;
    29.7 -        DPRINTK("Couldn't bind to PIRQ %d (error=%d)\n", pirq, rc);
    29.8          goto out;
    29.9      }
   29.10  
    30.1 --- a/xen/common/kernel.c	Wed Jul 28 13:45:22 2004 +0000
    30.2 +++ b/xen/common/kernel.c	Wed Jul 28 13:48:19 2004 +0000
    30.3 @@ -220,7 +220,7 @@ void cmain(multiboot_info_t *mbi)
    30.4          for ( ; ; ) ;
    30.5      }
    30.6  
    30.7 -    ASSERT((sizeof(struct pfn_info) << 20) >
    30.8 +    ASSERT((sizeof(struct pfn_info) << 20) <=
    30.9             (FRAMETABLE_VIRT_END - FRAMETABLE_VIRT_START));
   30.10  
   30.11      init_frametable((void *)FRAMETABLE_VIRT_START, max_page);
   30.12 @@ -258,15 +258,15 @@ void cmain(multiboot_info_t *mbi)
   30.13             max_page >> (20-PAGE_SHIFT), max_page,
   30.14  	   max_mem  >> (20-PAGE_SHIFT));
   30.15  
   30.16 -    add_to_domain_alloc_list(dom0_memory_end, max_page << PAGE_SHIFT);
   30.17 -
   30.18      heap_start = memguard_init(&_end);
   30.19 -
   30.20 +    heap_start = __va(init_heap_allocator(__pa(heap_start), max_page));
   30.21 + 
   30.22 +    init_xenheap_pages(__pa(heap_start), xenheap_phys_end);
   30.23      printk("Xen heap size is %luKB\n", 
   30.24  	   (xenheap_phys_end-__pa(heap_start))/1024 );
   30.25  
   30.26 -    init_page_allocator(__pa(heap_start), xenheap_phys_end);
   30.27 - 
   30.28 +    init_domheap_pages(dom0_memory_end, max_page << PAGE_SHIFT);
   30.29 +
   30.30      /* Initialise the slab allocator. */
   30.31      xmem_cache_init();
   30.32      xmem_cache_sizes_init(max_page);
   30.33 @@ -307,8 +307,8 @@ void cmain(multiboot_info_t *mbi)
   30.34          panic("Could not set up DOM0 guest OS\n");
   30.35  
   30.36      /* The stash space for the initial kernel image can now be freed up. */
   30.37 -    add_to_domain_alloc_list(__pa(frame_table) + frame_table_size,
   30.38 -                             dom0_memory_start);
   30.39 +    init_domheap_pages(__pa(frame_table) + frame_table_size,
   30.40 +                       dom0_memory_start);
   30.41  
   30.42      init_trace_bufs();
   30.43  
    31.1 --- a/xen/common/keyhandler.c	Wed Jul 28 13:45:22 2004 +0000
    31.2 +++ b/xen/common/keyhandler.c	Wed Jul 28 13:48:19 2004 +0000
    31.3 @@ -82,15 +82,15 @@ void do_task_queues(unsigned char key, v
    31.4              {
    31.5                  page = list_entry(ent, struct pfn_info, list);
    31.6                  printk("Page %08x: caf=%08x, taf=%08x\n",
    31.7 -                       page_to_phys(page), page->count_and_flags,
    31.8 -                       page->type_and_flags);
    31.9 +                       page_to_phys(page), page->u.inuse.count_info,
   31.10 +                       page->u.inuse.type_info);
   31.11              }
   31.12          }
   31.13  
   31.14          page = virt_to_page(d->shared_info);
   31.15          printk("Shared_info@%08x: caf=%08x, taf=%08x\n",
   31.16 -               page_to_phys(page), page->count_and_flags,
   31.17 -               page->type_and_flags);
   31.18 +               page_to_phys(page), page->u.inuse.count_info,
   31.19 +               page->u.inuse.type_info);
   31.20                 
   31.21          printk("Guest: upcall_pend = %02x, upcall_mask = %02x\n", 
   31.22                 d->shared_info->vcpu_data[0].evtchn_upcall_pending, 
    32.1 --- a/xen/common/memory.c	Wed Jul 28 13:45:22 2004 +0000
    32.2 +++ b/xen/common/memory.c	Wed Jul 28 13:48:19 2004 +0000
    32.3 @@ -37,10 +37,6 @@ struct pfn_info *frame_table;
    32.4  unsigned long frame_table_size;
    32.5  unsigned long max_page;
    32.6  
    32.7 -struct list_head free_list;
    32.8 -spinlock_t free_list_lock;
    32.9 -unsigned int free_pfns;
   32.10 -
   32.11  extern void init_percpu_info(void);
   32.12  
   32.13  void __init init_frametable(void *frametable_vstart, unsigned long nr_pages)
   32.14 @@ -59,10 +55,6 @@ void __init init_frametable(void *framet
   32.15  
   32.16      memset(frame_table, 0, frame_table_size);
   32.17  
   32.18 -    spin_lock_init(&free_list_lock);
   32.19 -    INIT_LIST_HEAD(&free_list);    
   32.20 -    free_pfns = 0;
   32.21 -
   32.22      /* Initialise to a magic of 0x55555555 so easier to spot bugs later. */
   32.23      memset(machine_to_phys_mapping, 0x55, 4<<20);
   32.24  
   32.25 @@ -71,23 +63,8 @@ void __init init_frametable(void *framet
   32.26            mfn < virt_to_phys(&machine_to_phys_mapping[1<<20])>>PAGE_SHIFT;
   32.27            mfn++ )
   32.28      {
   32.29 -        frame_table[mfn].count_and_flags = 1 | PGC_allocated;
   32.30 -        frame_table[mfn].type_and_flags = 1 | PGT_gdt_page; /* non-RW type */
   32.31 -        frame_table[mfn].u.domain = &idle0_task;
   32.32 +        frame_table[mfn].u.inuse.count_info = 1 | PGC_allocated;
   32.33 +        frame_table[mfn].u.inuse.type_info = 1 | PGT_gdt_page; /* non-RW */
   32.34 +        frame_table[mfn].u.inuse.domain = &idle0_task;
   32.35      }
   32.36  }
   32.37 -
   32.38 -
   32.39 -void add_to_domain_alloc_list(unsigned long ps, unsigned long pe)
   32.40 -{
   32.41 -    unsigned long i;
   32.42 -    unsigned long flags;
   32.43 -
   32.44 -    spin_lock_irqsave(&free_list_lock, flags);
   32.45 -    for ( i = ps >> PAGE_SHIFT; i < (pe >> PAGE_SHIFT); i++ )
   32.46 -    {
   32.47 -        list_add_tail(&frame_table[i].list, &free_list);
   32.48 -        free_pfns++;
   32.49 -    }
   32.50 -    spin_unlock_irqrestore(&free_list_lock, flags);
   32.51 -}
    33.1 --- a/xen/common/page_alloc.c	Wed Jul 28 13:45:22 2004 +0000
    33.2 +++ b/xen/common/page_alloc.c	Wed Jul 28 13:48:19 2004 +0000
    33.3 @@ -3,7 +3,7 @@
    33.4   * 
    33.5   * Simple buddy heap allocator for Xen.
    33.6   * 
    33.7 - * Copyright (c) 2002 K A Fraser
    33.8 + * Copyright (c) 2002-2004 K A Fraser
    33.9   * 
   33.10   * This program is free software; you can redistribute it and/or modify
   33.11   * it under the terms of the GNU General Public License as published by
   33.12 @@ -27,8 +27,7 @@
   33.13  #include <asm/page.h>
   33.14  #include <xen/spinlock.h>
   33.15  #include <xen/slab.h>
   33.16 -
   33.17 -static spinlock_t alloc_lock = SPIN_LOCK_UNLOCKED;
   33.18 +#include <xen/irq.h>
   33.19  
   33.20  
   33.21  /*********************
   33.22 @@ -115,210 +114,197 @@ static void map_free(unsigned long first
   33.23   * BINARY BUDDY ALLOCATOR
   33.24   */
   33.25  
   33.26 -typedef struct chunk_head_st chunk_head_t;
   33.27 +#define MEMZONE_XEN 0
   33.28 +#define MEMZONE_DOM 1
   33.29 +#define NR_ZONES    2
   33.30  
   33.31 -struct chunk_head_st {
   33.32 -    chunk_head_t  *next;
   33.33 -    chunk_head_t **pprev;
   33.34 -    int            level;
   33.35 -};
   33.36 +/* Up to 2^10 pages can be allocated at once. */
   33.37 +#define MIN_ORDER  0
   33.38 +#define MAX_ORDER 10
   33.39 +#define NR_ORDERS (MAX_ORDER - MIN_ORDER + 1)
   33.40 +static struct list_head heap[NR_ZONES][NR_ORDERS];
   33.41  
   33.42 -/* Linked lists of free chunks of different powers-of-two in size. */
   33.43 -#define FREELIST_SIZE ((sizeof(void*)<<3)-PAGE_SHIFT)
   33.44 -static chunk_head_t *free_head[FREELIST_SIZE];
   33.45 -static chunk_head_t  free_tail[FREELIST_SIZE];
   33.46 -#define FREELIST_EMPTY(_i) (free_head[_i] == &free_tail[i])
   33.47 +static unsigned long avail[NR_ZONES];
   33.48  
   33.49  #define round_pgdown(_p)  ((_p)&PAGE_MASK)
   33.50  #define round_pgup(_p)    (((_p)+(PAGE_SIZE-1))&PAGE_MASK)
   33.51  
   33.52 -#ifdef MEMORY_GUARD
   33.53 -
   33.54 -/*
   33.55 - * Debug build: free memory chunks are made inaccessible.
   33.56 - */
   33.57 -
   33.58 -/* Make order-'o' pages inaccessible, from address 'p'. */
   33.59 -static inline void GUARD(void *p, int o)
   33.60 -{
   33.61 -    p = (void *)((unsigned long)p&PAGE_MASK);
   33.62 -    if ( p > (void *)&_end ) /* careful not to protect the 'free_tail' array */
   33.63 -        memguard_guard_range(p, (1<<(o+PAGE_SHIFT)));
   33.64 -}
   33.65 -
   33.66 -/* Make order-'o' pages accessible, from address 'p'. */
   33.67 -static inline void UNGUARD(void *p, int o)
   33.68 -{
   33.69 -    p = (void *)((unsigned long)p&PAGE_MASK);
   33.70 -    if ( p > (void *)&_end ) /* careful not to protect the 'free_tail' array */
   33.71 -        memguard_unguard_range(p, (1<<(o+PAGE_SHIFT)));
   33.72 -}
   33.73 -
   33.74 -/* Safe form of 'ch->level'. */
   33.75 -static inline int HEAD_LEVEL(chunk_head_t *ch)
   33.76 -{
   33.77 -    int l;
   33.78 -    ASSERT(memguard_is_guarded(ch));
   33.79 -    UNGUARD(ch, 0);
   33.80 -    l = ch->level;
   33.81 -    GUARD(ch, 0);
   33.82 -    return l;
   33.83 -}
   33.84 -
   33.85 -/* Safe form of '*ch->pprev = l'. */
   33.86 -static inline void UPDATE_PREV_FORWARDLINK(chunk_head_t *ch, chunk_head_t *l)
   33.87 -{
   33.88 -    ASSERT(((void *)ch->pprev < (void *)&_end) || 
   33.89 -           memguard_is_guarded(ch->pprev));
   33.90 -    UNGUARD(ch->pprev, 0);
   33.91 -    *ch->pprev = l;
   33.92 -    GUARD(ch->pprev, 0);
   33.93 -}
   33.94 -
   33.95 -/* Safe form of 'ch->next->pprev = l'. */
   33.96 -static inline void UPDATE_NEXT_BACKLINK(chunk_head_t *ch, chunk_head_t **l)
   33.97 -{
   33.98 -    ASSERT(((void *)ch->next < (void *)&_end) || 
   33.99 -           memguard_is_guarded(ch->next));
  33.100 -    UNGUARD(ch->next, 0);
  33.101 -    ch->next->pprev = l;
  33.102 -    GUARD(ch->next, 0);
  33.103 -}
  33.104 -
  33.105 -#else
  33.106 -
  33.107 -/*
  33.108 - * Non-debug build: free memory chunks are not made inaccessible.
  33.109 - */
  33.110 -
  33.111 -#define GUARD(_p,_o) ((void)0)
  33.112 -#define UNGUARD(_p,_o) ((void)0)
  33.113 -#define HEAD_LEVEL(_ch) ((_ch)->level)
  33.114 -#define UPDATE_PREV_FORWARDLINK(_ch,_link) (*(_ch)->pprev = (_link))
  33.115 -#define UPDATE_NEXT_BACKLINK(_ch,_link) ((_ch)->next->pprev = (_link))
  33.116 -
  33.117 -#endif
  33.118 +static spinlock_t heap_lock = SPIN_LOCK_UNLOCKED;
  33.119  
  33.120  
  33.121 -/*
  33.122 - * Initialise allocator, placing addresses [@min,@max] in free pool.
  33.123 - * @min and @max are PHYSICAL addresses.
  33.124 - */
  33.125 -void __init init_page_allocator(unsigned long min, unsigned long max)
  33.126 +/* Initialise allocator to handle up to @max_pages. */
  33.127 +unsigned long init_heap_allocator(
  33.128 +    unsigned long bitmap_start, unsigned long max_pages)
  33.129  {
  33.130 -    int i;
  33.131 -    unsigned long range, bitmap_size, p, remaining;
  33.132 -    chunk_head_t *ch;
  33.133 +    int i, j;
  33.134 +    unsigned long bitmap_size;
  33.135  
  33.136 -    for ( i = 0; i < FREELIST_SIZE; i++ )
  33.137 -    {
  33.138 -        free_head[i]       = &free_tail[i];
  33.139 -        free_tail[i].pprev = &free_head[i];
  33.140 -        free_tail[i].next  = NULL;
  33.141 -    }
  33.142 +    memset(avail, 0, sizeof(avail));
  33.143  
  33.144 -    min = round_pgup  (min);
  33.145 -    max = round_pgdown(max);
  33.146 +    for ( i = 0; i < NR_ZONES; i++ )
  33.147 +        for ( j = 0; j < NR_ORDERS; j++ )
  33.148 +            INIT_LIST_HEAD(&heap[i][j]);
  33.149 +
  33.150 +    bitmap_start = round_pgup(bitmap_start);
  33.151  
  33.152      /* Allocate space for the allocation bitmap. */
  33.153 -    bitmap_size  = (max+1) >> (PAGE_SHIFT+3);
  33.154 +    bitmap_size  = max_pages / 8;
  33.155      bitmap_size  = round_pgup(bitmap_size);
  33.156 -    alloc_bitmap = (unsigned long *)phys_to_virt(min);
  33.157 -    min         += bitmap_size;
  33.158 -    range        = max - min;
  33.159 +    alloc_bitmap = (unsigned long *)phys_to_virt(bitmap_start);
  33.160  
  33.161      /* All allocated by default. */
  33.162      memset(alloc_bitmap, ~0, bitmap_size);
  33.163 +
  33.164 +    return bitmap_start + bitmap_size;
  33.165 +}
  33.166 +
  33.167 +/* Hand the specified arbitrary page range to the specified heap zone. */
  33.168 +void init_heap_pages(int zone, struct pfn_info *pg, unsigned long nr_pages)
  33.169 +{
  33.170 +    int i;
  33.171 +    unsigned long flags;
  33.172 +
  33.173 +    spin_lock_irqsave(&heap_lock, flags);
  33.174 +
  33.175      /* Free up the memory we've been given to play with. */
  33.176 -    map_free(min>>PAGE_SHIFT, range>>PAGE_SHIFT);
  33.177 +    map_free(page_to_pfn(pg), nr_pages);
  33.178 +    avail[zone] += nr_pages;
  33.179      
  33.180 -    /* The buddy lists are addressed in high memory. */
  33.181 -    min += PAGE_OFFSET;
  33.182 -    max += PAGE_OFFSET;
  33.183 -
  33.184 -    p         = min;
  33.185 -    remaining = range;
  33.186 -    while ( remaining != 0 )
  33.187 +    while ( nr_pages != 0 )
  33.188      {
  33.189          /*
  33.190 -         * Next chunk is limited by alignment of p, but also must not be bigger
  33.191 -         * than remaining bytes.
  33.192 +         * Next chunk is limited by alignment of pg, but also must not be
  33.193 +         * bigger than remaining bytes.
  33.194           */
  33.195 -        for ( i = PAGE_SHIFT; (1<<(i+1)) <= remaining; i++ )
  33.196 -            if ( p & (1<<i) ) break;
  33.197 +        for ( i = 0; i < MAX_ORDER; i++ )
  33.198 +            if ( ((page_to_pfn(pg) & (1 << i)) != 0) ||
  33.199 +                 ((1 << (i + 1)) > nr_pages) )
  33.200 +                break;
  33.201  
  33.202 -        ch = (chunk_head_t *)p;
  33.203 -        p         += (1<<i);
  33.204 -        remaining -= (1<<i);
  33.205 -        i -= PAGE_SHIFT;
  33.206 -        ch->level       = i;
  33.207 -        ch->next        = free_head[i];
  33.208 -        ch->pprev       = &free_head[i];
  33.209 -        ch->next->pprev = &ch->next;
  33.210 -        free_head[i]    = ch;
  33.211 +        PFN_ORDER(pg) = i;
  33.212 +        list_add_tail(&pg->list, &heap[zone][i]);
  33.213 +
  33.214 +        pg       += 1 << i;
  33.215 +        nr_pages -= 1 << i;
  33.216      }
  33.217  
  33.218 -    memguard_guard_range((void *)min, range);
  33.219 +    spin_unlock_irqrestore(&heap_lock, flags);
  33.220  }
  33.221  
  33.222  
  33.223 -/* Allocate 2^@order contiguous pages. Returns a VIRTUAL address. */
  33.224 -unsigned long alloc_xenheap_pages(int order)
  33.225 +/* Allocate 2^@order contiguous pages. */
  33.226 +struct pfn_info *alloc_heap_pages(int zone, int order)
  33.227  {
  33.228 -    int i, attempts = 0;
  33.229 -    chunk_head_t *alloc_ch, *spare_ch;
  33.230 -    unsigned long           flags;
  33.231 +    int i;
  33.232 +    struct pfn_info *pg;
  33.233 +    unsigned long flags;
  33.234  
  33.235 -retry:
  33.236 -    spin_lock_irqsave(&alloc_lock, flags);
  33.237 +    if ( unlikely(order < MIN_ORDER) || unlikely(order > MAX_ORDER) )
  33.238 +        return NULL;
  33.239 +
  33.240 +    spin_lock_irqsave(&heap_lock, flags);
  33.241  
  33.242      /* Find smallest order which can satisfy the request. */
  33.243 -    for ( i = order; i < FREELIST_SIZE; i++ )
  33.244 -	if ( !FREELIST_EMPTY(i) ) 
  33.245 +    for ( i = order; i < NR_ORDERS; i++ )
  33.246 +	if ( !list_empty(&heap[zone][i]) )
  33.247  	    break;
  33.248  
  33.249 -    if ( i == FREELIST_SIZE ) 
  33.250 +    if ( i == NR_ORDERS ) 
  33.251          goto no_memory;
  33.252   
  33.253 -    /* Unlink a chunk. */
  33.254 -    alloc_ch = free_head[i];
  33.255 -    UNGUARD(alloc_ch, i);
  33.256 -    free_head[i] = alloc_ch->next;
  33.257 -    /* alloc_ch->next->pprev = alloc_ch->pprev */
  33.258 -    UPDATE_NEXT_BACKLINK(alloc_ch, alloc_ch->pprev);
  33.259 +    pg = list_entry(heap[zone][i].next, struct pfn_info, list);
  33.260 +    list_del(&pg->list);
  33.261  
  33.262 -    /* We may have to break the chunk a number of times. */
  33.263 +    /* We may have to halve the chunk a number of times. */
  33.264      while ( i != order )
  33.265      {
  33.266 -        /* Split into two equal parts. */
  33.267 -        i--;
  33.268 -        spare_ch = (chunk_head_t *)((char *)alloc_ch + (1<<(i+PAGE_SHIFT)));
  33.269 -
  33.270 -        /* Create new header for spare chunk. */
  33.271 -        spare_ch->level = i;
  33.272 -        spare_ch->next  = free_head[i];
  33.273 -        spare_ch->pprev = &free_head[i];
  33.274 -
  33.275 -        /* Link in the spare chunk. */
  33.276 -        /* spare_ch->next->pprev = &spare_ch->next */
  33.277 -        UPDATE_NEXT_BACKLINK(spare_ch, &spare_ch->next);
  33.278 -        free_head[i] = spare_ch;
  33.279 -        GUARD(spare_ch, i);
  33.280 +        PFN_ORDER(pg) = --i;
  33.281 +        list_add_tail(&pg->list, &heap[zone][i]);
  33.282 +        pg += 1 << i;
  33.283      }
  33.284      
  33.285 -    map_alloc(virt_to_phys(alloc_ch)>>PAGE_SHIFT, 1<<order);
  33.286 -
  33.287 -    spin_unlock_irqrestore(&alloc_lock, flags);
  33.288 +    map_alloc(page_to_pfn(pg), 1 << order);
  33.289 +    avail[zone] -= 1 << order;
  33.290  
  33.291 -#ifdef MEMORY_GUARD
  33.292 -    memset(alloc_ch, 0x55, 1 << (order + PAGE_SHIFT));
  33.293 -#endif
  33.294 +    spin_unlock_irqrestore(&heap_lock, flags);
  33.295  
  33.296 -    return((unsigned long)alloc_ch);
  33.297 +    return pg;
  33.298  
  33.299   no_memory:
  33.300 -    spin_unlock_irqrestore(&alloc_lock, flags);
  33.301 +    spin_unlock_irqrestore(&heap_lock, flags);
  33.302 +    return NULL;
  33.303 +}
  33.304 +
  33.305 +
  33.306 +/* Free 2^@order set of pages. */
  33.307 +void free_heap_pages(int zone, struct pfn_info *pg, int order)
  33.308 +{
  33.309 +    unsigned long mask;
  33.310 +    unsigned long flags;
  33.311 +
  33.312 +    spin_lock_irqsave(&heap_lock, flags);
  33.313 +
  33.314 +    map_free(page_to_pfn(pg), 1 << order);
  33.315 +    avail[zone] += 1 << order;
  33.316 +    
  33.317 +    /* Merge chunks as far as possible. */
  33.318 +    while ( order < MAX_ORDER )
  33.319 +    {
  33.320 +        mask = 1 << order;
  33.321 +
  33.322 +        if ( (page_to_pfn(pg) & mask) )
  33.323 +        {
  33.324 +            /* Merge with predecessor block? */
  33.325 +            if ( allocated_in_map(page_to_pfn(pg)-mask) ||
  33.326 +                 (PFN_ORDER(pg-mask) != order) )
  33.327 +                break;
  33.328 +            list_del(&(pg-mask)->list);
  33.329 +            pg -= mask;
  33.330 +        }
  33.331 +        else
  33.332 +        {
  33.333 +            /* Merge with successor block? */
  33.334 +            if ( allocated_in_map(page_to_pfn(pg)+mask) ||
  33.335 +                 (PFN_ORDER(pg+mask) != order) )
  33.336 +                break;
  33.337 +            list_del(&(pg+mask)->list);
  33.338 +        }
  33.339          
  33.340 +        order++;
  33.341 +    }
  33.342 +
  33.343 +    PFN_ORDER(pg) = order;
  33.344 +    list_add_tail(&pg->list, &heap[zone][order]);
  33.345 +
  33.346 +    spin_unlock_irqrestore(&heap_lock, flags);
  33.347 +}
  33.348 +
  33.349 +
  33.350 +
  33.351 +/*************************
  33.352 + * XEN-HEAP SUB-ALLOCATOR
  33.353 + */
  33.354 +
  33.355 +void init_xenheap_pages(unsigned long ps, unsigned long pe)
  33.356 +{
  33.357 +    ps = round_pgup(ps);
  33.358 +    pe = round_pgdown(pe);
  33.359 +    memguard_guard_range(__va(ps), pe - ps);
  33.360 +    init_heap_pages(MEMZONE_XEN, phys_to_page(ps), (pe - ps) >> PAGE_SHIFT);
  33.361 +}
  33.362 +
  33.363 +unsigned long alloc_xenheap_pages(int order)
  33.364 +{
  33.365 +    struct pfn_info *pg;
  33.366 +    int attempts = 0;
  33.367 +
  33.368 + retry:
  33.369 +    if ( unlikely((pg = alloc_heap_pages(MEMZONE_XEN, order)) == NULL) )
  33.370 +        goto no_memory;
  33.371 +    memguard_unguard_range(page_to_virt(pg), 1 << (order + PAGE_SHIFT));
  33.372 +    return (unsigned long)page_to_virt(pg);
  33.373 +
  33.374 + no_memory:
  33.375      if ( attempts++ < 8 )
  33.376      {
  33.377          xmem_cache_reap();
  33.378 @@ -327,71 +313,138 @@ retry:
  33.379  
  33.380      printk("Cannot handle page request order %d!\n", order);
  33.381      dump_slabinfo();
  33.382 +    return 0;
  33.383 +}
  33.384  
  33.385 -    return 0;
  33.386 +void free_xenheap_pages(unsigned long p, int order)
  33.387 +{
  33.388 +    memguard_guard_range((void *)p, 1 << (order + PAGE_SHIFT));    
  33.389 +    free_heap_pages(MEMZONE_XEN, virt_to_page(p), order);
  33.390  }
  33.391  
  33.392  
  33.393 -/* Free 2^@order pages at VIRTUAL address @p. */
  33.394 -void free_xenheap_pages(unsigned long p, int order)
  33.395 +
  33.396 +/*************************
  33.397 + * DOMAIN-HEAP SUB-ALLOCATOR
  33.398 + */
  33.399 +
  33.400 +void init_domheap_pages(unsigned long ps, unsigned long pe)
  33.401  {
  33.402 -    unsigned long size = 1 << (order + PAGE_SHIFT);
  33.403 -    chunk_head_t *ch;
  33.404 -    unsigned long flags;
  33.405 -    unsigned long pfn = virt_to_phys((void *)p) >> PAGE_SHIFT;
  33.406 -
  33.407 -    spin_lock_irqsave(&alloc_lock, flags);
  33.408 +    ps = round_pgup(ps);
  33.409 +    pe = round_pgdown(pe);
  33.410 +    init_heap_pages(MEMZONE_DOM, phys_to_page(ps), (pe - ps) >> PAGE_SHIFT);
  33.411 +}
  33.412  
  33.413 -#ifdef MEMORY_GUARD
  33.414 -    memset((void *)p, 0xaa, size);
  33.415 -#endif
  33.416 +struct pfn_info *alloc_domheap_pages(struct domain *d, int order)
  33.417 +{
  33.418 +    struct pfn_info *pg;
  33.419 +    unsigned long mask, flushed_mask, pfn_stamp, cpu_stamp;
  33.420 +    int i;
  33.421 +
  33.422 +    ASSERT(!in_irq());
  33.423  
  33.424 -    map_free(pfn, 1<<order);
  33.425 -    
  33.426 -    /* Merge chunks as far as possible. */
  33.427 -    for ( ; ; )
  33.428 +    if ( unlikely((pg = alloc_heap_pages(MEMZONE_DOM, order)) == NULL) )
  33.429 +        return NULL;
  33.430 +
  33.431 +    flushed_mask = 0;
  33.432 +    for ( i = 0; i < (1 << order); i++ )
  33.433      {
  33.434 -        if ( (p & size) )
  33.435 +        pg[i].u.inuse.domain    = NULL;
  33.436 +        pg[i].u.inuse.type_info = 0;
  33.437 +
  33.438 +        if ( (mask = (pg[i].u.free.cpu_mask & ~flushed_mask)) != 0 )
  33.439          {
  33.440 -            /* Merge with predecessor block? */
  33.441 -            if ( allocated_in_map(pfn-(1<<order)) )
  33.442 -                break;
  33.443 -            ch = (chunk_head_t *)(p - size);
  33.444 -            if ( HEAD_LEVEL(ch) != order )
  33.445 -                break;
  33.446 -            p   -= size;
  33.447 -            pfn -= 1<<order;
  33.448 +            pfn_stamp = pg[i].tlbflush_timestamp;
  33.449 +            for ( i = 0; (mask != 0) && (i < smp_num_cpus); i++ )
  33.450 +            {
  33.451 +                if ( mask & (1<<i) )
  33.452 +                {
  33.453 +                    cpu_stamp = tlbflush_time[i];
  33.454 +                    if ( !NEED_FLUSH(cpu_stamp, pfn_stamp) )
  33.455 +                        mask &= ~(1<<i);
  33.456 +                }
  33.457 +            }
  33.458 +            
  33.459 +            if ( unlikely(mask != 0) )
  33.460 +            {
  33.461 +                flush_tlb_mask(mask);
  33.462 +                perfc_incrc(need_flush_tlb_flush);
  33.463 +                flushed_mask |= mask;
  33.464 +            }
  33.465          }
  33.466 -        else
  33.467 -        {
  33.468 -            /* Merge with successor block? */
  33.469 -            if ( allocated_in_map(pfn+(1<<order)) )
  33.470 -                break;
  33.471 -            ch = (chunk_head_t *)(p + size);
  33.472 -            if ( HEAD_LEVEL(ch) != order )
  33.473 -                break;
  33.474 -        }
  33.475 -        
  33.476 -        /* Okay, unlink the neighbour. */
  33.477 -        UNGUARD(ch, order);
  33.478 -        /* *ch->pprev = ch->next */
  33.479 -        UPDATE_PREV_FORWARDLINK(ch, ch->next);
  33.480 -        /* ch->next->pprev = ch->pprev */
  33.481 -        UPDATE_NEXT_BACKLINK(ch, ch->pprev);
  33.482 -
  33.483 -        order++;
  33.484 -        size <<= 1;
  33.485      }
  33.486  
  33.487 -    /* Okay, add the final chunk to the appropriate free list. */
  33.488 -    ch = (chunk_head_t *)p;
  33.489 -    ch->level = order;
  33.490 -    ch->pprev = &free_head[order];
  33.491 -    ch->next  = free_head[order];
  33.492 -    /* ch->next->pprev = &ch->next */
  33.493 -    UPDATE_NEXT_BACKLINK(ch, &ch->next);
  33.494 -    free_head[order] = ch;
  33.495 -    GUARD(ch, order);
  33.496 +    if ( d == NULL )
  33.497 +        return pg;
  33.498 +
  33.499 +    spin_lock(&d->page_alloc_lock);
  33.500 +
  33.501 +    if ( unlikely((d->tot_pages + (1 << order)) > d->max_pages) )
  33.502 +    {
  33.503 +        DPRINTK("Over-allocation for domain %u: %u > %u\n",
  33.504 +                d->domain, d->tot_pages + (1 << order), d->max_pages);
  33.505 +        spin_unlock(&d->page_alloc_lock);
  33.506 +        free_heap_pages(MEMZONE_DOM, pg, order);
  33.507 +        return NULL;
  33.508 +    }
  33.509 +
  33.510 +    if ( unlikely(d->tot_pages == 0) )
  33.511 +        get_domain(d);
  33.512 +
  33.513 +    d->tot_pages += 1 << order;
  33.514 +
  33.515 +    for ( i = 0; i < (1 << order); i++ )
  33.516 +    {
  33.517 +        pg[i].u.inuse.domain = d;
  33.518 +        wmb(); /* Domain pointer must be visible before updating refcnt. */
  33.519 +        pg->u.inuse.count_info = PGC_allocated | 1;
  33.520 +        list_add_tail(&pg->list, &d->page_list);
  33.521 +    }
  33.522 +
  33.523 +    spin_unlock(&d->page_alloc_lock);
  33.524 +    
  33.525 +    return pg;
  33.526 +}
  33.527 +
  33.528 +void free_domheap_pages(struct pfn_info *pg, int order)
  33.529 +{
  33.530 +    int            i, drop_dom_ref;
  33.531 +    struct domain *d = pg->u.inuse.domain;
  33.532  
  33.533 -    spin_unlock_irqrestore(&alloc_lock, flags);
  33.534 +    if ( unlikely(IS_XEN_HEAP_FRAME(pg)) )
  33.535 +    {
  33.536 +        spin_lock_recursive(&d->page_alloc_lock);
  33.537 +        d->xenheap_pages -= 1 << order;
  33.538 +        drop_dom_ref = (d->xenheap_pages == 0);
  33.539 +        spin_unlock_recursive(&d->page_alloc_lock);
  33.540 +    }
  33.541 +    else
  33.542 +    {
  33.543 +        /* NB. May recursively lock from domain_relinquish_memory(). */
  33.544 +        spin_lock_recursive(&d->page_alloc_lock);
  33.545 +
  33.546 +        for ( i = 0; i < (1 << order); i++ )
  33.547 +        {
  33.548 +            pg[i].tlbflush_timestamp = tlbflush_clock;
  33.549 +            pg[i].u.inuse.count_info = 0;
  33.550 +            pg[i].u.free.cpu_mask    = 1 << d->processor;
  33.551 +            list_del(&pg[i].list);
  33.552 +        }
  33.553 +
  33.554 +        d->tot_pages -= 1 << order;
  33.555 +        drop_dom_ref = (d->tot_pages == 0);
  33.556 +
  33.557 +        spin_unlock_recursive(&d->page_alloc_lock);
  33.558 +
  33.559 +        free_heap_pages(MEMZONE_DOM, pg, order);
  33.560 +    }
  33.561 +
  33.562 +    if ( drop_dom_ref )
  33.563 +        put_domain(d);
  33.564  }
  33.565 +
  33.566 +unsigned long avail_domheap_pages(void)
  33.567 +{
  33.568 +    return avail[MEMZONE_DOM];
  33.569 +}
  33.570 +
    34.1 --- a/xen/common/sched_bvt.c	Wed Jul 28 13:45:22 2004 +0000
    34.2 +++ b/xen/common/sched_bvt.c	Wed Jul 28 13:48:19 2004 +0000
    34.3 @@ -148,11 +148,11 @@ int bvt_init_idle_task(struct domain *p)
    34.4  
    34.5      bvt_add_task(p);
    34.6  
    34.7 -    spin_lock_irqsave(&schedule_lock[p->processor], flags);
    34.8 +    spin_lock_irqsave(&schedule_data[p->processor].schedule_lock, flags);
    34.9      set_bit(DF_RUNNING, &p->flags);
   34.10      if ( !__task_on_runqueue(RUNLIST(p)) )
   34.11          __add_to_runqueue_head(RUNLIST(p), RUNQUEUE(p->processor));
   34.12 -    spin_unlock_irqrestore(&schedule_lock[p->processor], flags);
   34.13 +    spin_unlock_irqrestore(&schedule_data[p->processor].schedule_lock, flags);
   34.14  
   34.15      return 0;
   34.16  }
   34.17 @@ -218,7 +218,7 @@ int bvt_adjdom(struct domain *p,
   34.18          if ( mcu_adv == 0 )
   34.19              return -EINVAL;
   34.20          
   34.21 -        spin_lock_irqsave(&schedule_lock[p->processor], flags);   
   34.22 +        spin_lock_irqsave(&schedule_data[p->processor].schedule_lock, flags);   
   34.23          inf->mcu_advance = mcu_adv;
   34.24          inf->warp = warp;
   34.25          inf->warpl = warpl;
   34.26 @@ -229,18 +229,18 @@ int bvt_adjdom(struct domain *p,
   34.27                  p->domain, inf->mcu_advance, inf->warp,
   34.28                  inf->warpl, inf->warpu );
   34.29  
   34.30 -        spin_unlock_irqrestore(&schedule_lock[p->processor], flags);
   34.31 +        spin_unlock_irqrestore(&schedule_data[p->processor].schedule_lock, flags);
   34.32      }
   34.33      else if ( cmd->direction == SCHED_INFO_GET )
   34.34      {
   34.35          struct bvt_dom_info *inf = BVT_INFO(p);
   34.36  
   34.37 -        spin_lock_irqsave(&schedule_lock[p->processor], flags);   
   34.38 +        spin_lock_irqsave(&schedule_data[p->processor].schedule_lock, flags);   
   34.39          params->mcu_adv = inf->mcu_advance;
   34.40          params->warp    = inf->warp;
   34.41          params->warpl   = inf->warpl;
   34.42          params->warpu   = inf->warpu;
   34.43 -        spin_unlock_irqrestore(&schedule_lock[p->processor], flags);
   34.44 +        spin_unlock_irqrestore(&schedule_data[p->processor].schedule_lock, flags);
   34.45      }
   34.46      
   34.47      return 0;
   34.48 @@ -411,7 +411,7 @@ static void bvt_dump_cpu_state(int i)
   34.49      struct bvt_dom_info *d_inf;
   34.50      struct domain *d;
   34.51      
   34.52 -    spin_lock_irqsave(&schedule_lock[i], flags);
   34.53 +    spin_lock_irqsave(&schedule_data[i].schedule_lock, flags);
   34.54      printk("svt=0x%08lX ", CPU_SVT(i));
   34.55  
   34.56      queue = RUNQUEUE(i);
   34.57 @@ -430,7 +430,7 @@ static void bvt_dump_cpu_state(int i)
   34.58              (unsigned long)list, (unsigned long)list->next,
   34.59              (unsigned long)list->prev);
   34.60      }
   34.61 -    spin_unlock_irqrestore(&schedule_lock[i], flags);        
   34.62 +    spin_unlock_irqrestore(&schedule_data[i].schedule_lock, flags);        
   34.63  }
   34.64  
   34.65  /* We use cache to create the bvt_dom_infos 
    35.1 --- a/xen/common/sched_fair_bvt.c	Wed Jul 28 13:45:22 2004 +0000
    35.2 +++ b/xen/common/sched_fair_bvt.c	Wed Jul 28 13:48:19 2004 +0000
    35.3 @@ -160,12 +160,11 @@ int fbvt_init_idle_task(struct domain *p
    35.4      if(fbvt_alloc_task(p) < 0) return -1;
    35.5  
    35.6      fbvt_add_task(p);
    35.7 -//printk("< ----- >Initialising idle task for processor %d, address %d, priv %d\n", p->processor, (int)p, (int)p->sched_priv);
    35.8 -    spin_lock_irqsave(&schedule_lock[p->processor], flags);
    35.9 +    spin_lock_irqsave(&schedule_data[p->processor].schedule_lock, flags);
   35.10      set_bit(DF_RUNNING, &p->flags);
   35.11      if ( !__task_on_runqueue(RUNLIST(p)) )
   35.12      __add_to_runqueue_head(RUNLIST(p), RUNQUEUE(p->processor));
   35.13 -    spin_unlock_irqrestore(&schedule_lock[p->processor], flags);
   35.14 +    spin_unlock_irqrestore(&schedule_data[p->processor].schedule_lock, flags);
   35.15  
   35.16      return 0;
   35.17  }
   35.18 @@ -233,7 +232,7 @@ int fbvt_adjdom(struct domain *p,
   35.19          if ( mcu_adv == 0 )
   35.20              return -EINVAL;
   35.21          
   35.22 -        spin_lock_irqsave(&schedule_lock[p->processor], flags);   
   35.23 +        spin_lock_irqsave(&schedule_data[p->processor].schedule_lock, flags);   
   35.24          inf->mcu_advance = mcu_adv;
   35.25          inf->warp = warp;
   35.26          inf->warpl = warpl;
   35.27 @@ -244,18 +243,20 @@ int fbvt_adjdom(struct domain *p,
   35.28                  p->domain, inf->mcu_advance, inf->warp,
   35.29                  inf->warpl, inf->warpu );
   35.30  
   35.31 -        spin_unlock_irqrestore(&schedule_lock[p->processor], flags);
   35.32 +        spin_unlock_irqrestore(&schedule_data[p->processor].schedule_lock, 
   35.33 +                                                                        flags);
   35.34      }
   35.35      else if ( cmd->direction == SCHED_INFO_GET )
   35.36      {
   35.37          struct fbvt_dom_info *inf = FBVT_INFO(p);
   35.38  
   35.39 -        spin_lock_irqsave(&schedule_lock[p->processor], flags);   
   35.40 +        spin_lock_irqsave(&schedule_data[p->processor].schedule_lock, flags);   
   35.41          params->mcu_adv = inf->mcu_advance;
   35.42          params->warp    = inf->warp;
   35.43          params->warpl   = inf->warpl;
   35.44          params->warpu   = inf->warpu;
   35.45 -        spin_unlock_irqrestore(&schedule_lock[p->processor], flags);
   35.46 +        spin_unlock_irqrestore(&schedule_data[p->processor].schedule_lock, 
   35.47 +                                                                        flags);
   35.48      }
   35.49      
   35.50      return 0;
   35.51 @@ -285,7 +286,6 @@ static task_slice_t fbvt_do_schedule(s_t
   35.52      struct fbvt_dom_info *next_prime_inf = NULL;
   35.53      task_slice_t        ret;
   35.54  
   35.55 -//if(prev->sched_priv == NULL) printk("----> %d\n", prev->domain);
   35.56      ASSERT(prev->sched_priv != NULL);
   35.57      ASSERT(prev_inf != NULL);
   35.58  
   35.59 @@ -450,7 +450,6 @@ static task_slice_t fbvt_do_schedule(s_t
   35.60      next->min_slice = ctx_allow;
   35.61      ret.task = next;
   35.62      ret.time = r_time;
   35.63 -//printk("NEXT --> domain %d (address %d, processor %d), priv %d\n",next->domain, (int)next, next->processor, (int)next->sched_priv); 
   35.64      return ret;
   35.65  }
   35.66  
   35.67 @@ -476,7 +475,7 @@ static void fbvt_dump_cpu_state(int i)
   35.68      struct fbvt_dom_info *d_inf;
   35.69      struct domain *d;
   35.70  
   35.71 -    spin_lock_irqsave(&schedule_lock[i], flags);
   35.72 +    spin_lock_irqsave(&schedule_data[i].schedule_lock, flags);
   35.73      printk("svt=0x%08lX ", CPU_SVT(i));
   35.74  
   35.75      queue = RUNQUEUE(i);
   35.76 @@ -495,7 +494,7 @@ static void fbvt_dump_cpu_state(int i)
   35.77              (unsigned long)list, (unsigned long)list->next,
   35.78              (unsigned long)list->prev);
   35.79      }
   35.80 -    spin_unlock_irqrestore(&schedule_lock[i], flags);
   35.81 +    spin_unlock_irqrestore(&schedule_data[i].schedule_lock, flags);
   35.82  }
   35.83  
   35.84  
   35.85 @@ -559,14 +558,10 @@ static void fbvt_wake(struct domain *d)
   35.86      int                   cpu = d->processor;
   35.87      s32                   io_warp;
   35.88  
   35.89 -//printk("-|--> Adding new domain %d\n",d->domain);
   35.90 -//printk("-|--> Current%d  (address %d, processor %d)  %d\n",current->domain,(int)current, current->processor, (int)current->sched_priv);
   35.91      /* If on the runqueue already then someone has done the wakeup work. */
   35.92      if ( unlikely(__task_on_runqueue(RUNLIST(d))) )
   35.93          return;
   35.94 -//printk("----> Not on runqueue\n");
   35.95      __add_to_runqueue_head(RUNLIST(d), RUNQUEUE(cpu));
   35.96 -//printk(" ---> %d\n",(int)current->sched_priv);
   35.97   
   35.98      now = NOW();
   35.99  
  35.100 @@ -617,7 +612,6 @@ static void fbvt_wake(struct domain *d)
  35.101      __calc_evt(inf);
  35.102  
  35.103      curr = schedule_data[cpu].curr;
  35.104 -//printk(" ---> %d\n",(int)current->sched_priv);
  35.105   
  35.106      /* Currently-running domain should run at least for ctx_allow. */
  35.107      min_time = curr->lastschd + curr->min_slice;
  35.108 @@ -626,7 +620,6 @@ static void fbvt_wake(struct domain *d)
  35.109          cpu_raise_softirq(cpu, SCHEDULE_SOFTIRQ);
  35.110      else if ( schedule_data[cpu].s_timer.expires > (min_time + TIME_SLOP) )
  35.111          mod_ac_timer(&schedule_data[cpu].s_timer, min_time);
  35.112 -//printk(" ---> %d\n",(int)current->sched_priv);
  35.113  } 
  35.114  
  35.115  struct scheduler sched_fbvt_def = {
    36.1 --- a/xen/common/sched_rrobin.c	Wed Jul 28 13:45:22 2004 +0000
    36.2 +++ b/xen/common/sched_rrobin.c	Wed Jul 28 13:48:19 2004 +0000
    36.3 @@ -95,11 +95,11 @@ static int rr_init_idle_task(struct doma
    36.4      if(rr_alloc_task(p) < 0) return -1;
    36.5      rr_add_task(p);
    36.6  
    36.7 -    spin_lock_irqsave(&schedule_lock[p->processor], flags);
    36.8 +    spin_lock_irqsave(&schedule_data[p->processor].schedule_lock, flags);
    36.9      set_bit(DF_RUNNING, &p->flags);
   36.10      if ( !__task_on_runqueue(RUNLIST(p)) )
   36.11           __add_to_runqueue_head(RUNLIST(p), RUNQUEUE(p->processor));
   36.12 -    spin_unlock_irqrestore(&schedule_lock[p->processor], flags);
   36.13 +    spin_unlock_irqrestore(&schedule_data[p->processor].schedule_lock, flags);
   36.14      return 0;
   36.15  }
   36.16  
   36.17 @@ -194,7 +194,7 @@ static void rr_dump_cpu_state(int i)
   36.18      int loop = 0;
   36.19      struct rrobin_dom_info *d_inf;
   36.20  
   36.21 -    spin_lock_irqsave(&schedule_lock[i], flags);
   36.22 +    spin_lock_irqsave(&schedule_data[i].schedule_lock, flags);
   36.23  
   36.24      queue = RUNQUEUE(i);
   36.25      printk("QUEUE rq %lx   n: %lx, p: %lx\n",  (unsigned long)queue,
   36.26 @@ -210,7 +210,7 @@ static void rr_dump_cpu_state(int i)
   36.27          d_inf = list_entry(list, struct rrobin_dom_info, run_list);
   36.28          rr_dump_domain(d_inf->domain);
   36.29      }
   36.30 -    spin_unlock_irqrestore(&schedule_lock[i], flags);
   36.31 +    spin_unlock_irqrestore(&schedule_data[i].schedule_lock, flags);
   36.32  }
   36.33  
   36.34  
    37.1 --- a/xen/common/schedule.c	Wed Jul 28 13:45:22 2004 +0000
    37.2 +++ b/xen/common/schedule.c	Wed Jul 28 13:48:19 2004 +0000
    37.3 @@ -85,8 +85,6 @@ static struct scheduler ops;
    37.4           (( ops.fn != NULL ) ? ops.fn( __VA_ARGS__ )      \
    37.5            : (typeof(ops.fn(__VA_ARGS__)))0 )
    37.6  
    37.7 -spinlock_t schedule_lock[NR_CPUS] __cacheline_aligned;
    37.8 -
    37.9  /* Per-CPU periodic timer sends an event to the currently-executing domain. */
   37.10  static struct ac_timer t_timer[NR_CPUS]; 
   37.11  
   37.12 @@ -168,10 +166,10 @@ void domain_sleep(struct domain *d)
   37.13      unsigned long flags;
   37.14      int           cpu = d->processor;
   37.15  
   37.16 -    spin_lock_irqsave(&schedule_lock[cpu], flags);
   37.17 +    spin_lock_irqsave(&schedule_data[cpu].schedule_lock, flags);
   37.18      if ( likely(!domain_runnable(d)) )
   37.19          SCHED_OP(sleep, d);
   37.20 -    spin_unlock_irqrestore(&schedule_lock[cpu], flags);
   37.21 +    spin_unlock_irqrestore(&schedule_data[cpu].schedule_lock, flags);
   37.22  
   37.23      /* Synchronous. */
   37.24      while ( test_bit(DF_RUNNING, &d->flags) && !domain_runnable(d) )
   37.25 @@ -185,7 +183,7 @@ void domain_wake(struct domain *d)
   37.26  {
   37.27      unsigned long       flags;
   37.28      int                 cpu = d->processor;
   37.29 -    spin_lock_irqsave(&schedule_lock[cpu], flags);
   37.30 +    spin_lock_irqsave(&schedule_data[cpu].schedule_lock, flags);
   37.31      if ( likely(domain_runnable(d)) )
   37.32      {
   37.33          TRACE_2D(TRC_SCHED_WAKE, d->domain, d);
   37.34 @@ -194,7 +192,7 @@ void domain_wake(struct domain *d)
   37.35          d->wokenup = NOW();
   37.36  #endif
   37.37      }
   37.38 -    spin_unlock_irqrestore(&schedule_lock[cpu], flags);
   37.39 +    spin_unlock_irqrestore(&schedule_data[cpu].schedule_lock, flags);
   37.40  }
   37.41  
   37.42  /* Block the currently-executing domain until a pertinent event occurs. */
   37.43 @@ -326,7 +324,7 @@ void __enter_scheduler(void)
   37.44  
   37.45      perfc_incrc(sched_run);
   37.46  
   37.47 -    spin_lock_irq(&schedule_lock[cpu]);
   37.48 +    spin_lock_irq(&schedule_data[cpu].schedule_lock);
   37.49  
   37.50      now = NOW();
   37.51  
   37.52 @@ -360,7 +358,7 @@ void __enter_scheduler(void)
   37.53      schedule_data[cpu].s_timer.expires  = now + r_time;
   37.54      add_ac_timer(&schedule_data[cpu].s_timer);
   37.55  
   37.56 -    spin_unlock_irq(&schedule_lock[cpu]);
   37.57 +    spin_unlock_irq(&schedule_data[cpu].schedule_lock);
   37.58  
   37.59      /* Ensure that the domain has an up-to-date time base. */
   37.60      if ( !is_idle_task(next) )
   37.61 @@ -481,7 +479,7 @@ void __init scheduler_init(void)
   37.62  
   37.63      for ( i = 0; i < NR_CPUS; i++ )
   37.64      {
   37.65 -        spin_lock_init(&schedule_lock[i]);
   37.66 +        spin_lock_init(&schedule_data[i].schedule_lock);
   37.67          schedule_data[i].curr = &idle0_task;
   37.68          
   37.69          init_ac_timer(&schedule_data[i].s_timer);
    38.1 --- a/xen/include/asm-x86/config.h	Wed Jul 28 13:45:22 2004 +0000
    38.2 +++ b/xen/include/asm-x86/config.h	Wed Jul 28 13:48:19 2004 +0000
    38.3 @@ -58,12 +58,6 @@
    38.4  #define __cacheline_aligned __attribute__((__aligned__(SMP_CACHE_BYTES)))
    38.5  #define ____cacheline_aligned __cacheline_aligned
    38.6  
    38.7 -/*
    38.8 - * Amount of slack domain memory to leave in system, in megabytes.
    38.9 - * Prevents a hard out-of-memory crunch for things like network receive.
   38.10 - */
   38.11 -#define SLACK_DOMAIN_MEM_KILOBYTES 2048
   38.12 -
   38.13  /* Linkage for x86 */
   38.14  #define asmlinkage        __attribute__((regparm(0)))
   38.15  #define __ALIGN .align 16,0x90
    39.1 --- a/xen/include/asm-x86/domain.h	Wed Jul 28 13:45:22 2004 +0000
    39.2 +++ b/xen/include/asm-x86/domain.h	Wed Jul 28 13:48:19 2004 +0000
    39.3 @@ -7,10 +7,7 @@ extern void arch_do_createdomain(struct 
    39.4  extern void arch_final_setup_guestos(
    39.5      struct domain *d, full_execution_context_t *c);
    39.6  
    39.7 -static inline void free_perdomain_pt(struct domain *d)
    39.8 -{
    39.9 -    free_xenheap_page((unsigned long)d->mm.perdomain_pt);
   39.10 -}
   39.11 +extern void free_perdomain_pt(struct domain *d);
   39.12  
   39.13  extern void domain_relinquish_memory(struct domain *d);
   39.14  
    40.1 --- a/xen/include/asm-x86/mm.h	Wed Jul 28 13:45:22 2004 +0000
    40.2 +++ b/xen/include/asm-x86/mm.h	Wed Jul 28 13:48:19 2004 +0000
    40.3 @@ -18,23 +18,43 @@
    40.4  
    40.5  /*
    40.6   * Per-page-frame information.
    40.7 + * 
    40.8 + * Every architecture must ensure the following:
    40.9 + *  1. 'struct pfn_info' contains a 'struct list_head list'.
   40.10 + *  2. Provide a PFN_ORDER() macro for accessing the order of a free page.
   40.11   */
   40.12 +#define PFN_ORDER(_pfn) ((_pfn)->u.free.order)
   40.13  
   40.14  struct pfn_info
   40.15  {
   40.16      /* Each frame can be threaded onto a doubly-linked list. */
   40.17      struct list_head list;
   40.18 -    /* The following possible uses are context-dependent. */
   40.19 +
   40.20 +    /* Context-dependent fields follow... */
   40.21      union {
   40.22 -        /* Page is in use: we keep a pointer to its owner. */
   40.23 -        struct domain *domain;
   40.24 -        /* Page is not currently allocated: mask of possibly-tainted TLBs. */
   40.25 -        unsigned long cpu_mask;
   40.26 +
   40.27 +        /* Page is in use by a domain. */
   40.28 +        struct {
   40.29 +            /* Owner of this page. */
   40.30 +            struct domain *domain;
   40.31 +            /* Reference count and various PGC_xxx flags and fields. */
   40.32 +            u32 count_info;
   40.33 +            /* Type reference count and various PGT_xxx flags and fields. */
   40.34 +            u32 type_info;
   40.35 +        } inuse;
   40.36 +
   40.37 +        /* Page is on a free list. */
   40.38 +        struct {
   40.39 +            /* Mask of possibly-tainted TLBs. */
   40.40 +            unsigned long cpu_mask;
   40.41 +            /* Must be at same offset as 'u.inuse.count_flags'. */
   40.42 +            u32 __unavailable;
   40.43 +            /* Order-size of the free chunk this page is the head of. */
   40.44 +            u8 order;
   40.45 +        } free;
   40.46 +
   40.47      } u;
   40.48 -    /* Reference count and various PGC_xxx flags and fields. */
   40.49 -    u32 count_and_flags;
   40.50 -    /* Type reference count and various PGT_xxx flags and fields. */
   40.51 -    u32 type_and_flags;
   40.52 +
   40.53      /* Timestamp from 'TLB clock', used to reduce need for safety flushes. */
   40.54      u32 tlbflush_timestamp;
   40.55  };
   40.56 @@ -77,13 +97,13 @@ struct pfn_info
   40.57  
   40.58  #define SHARE_PFN_WITH_DOMAIN(_pfn, _dom)                                   \
   40.59      do {                                                                    \
   40.60 -        (_pfn)->u.domain = (_dom);                                          \
   40.61 +        (_pfn)->u.inuse.domain = (_dom);                                    \
   40.62          /* The incremented type count is intended to pin to 'writeable'. */ \
   40.63 -        (_pfn)->type_and_flags  = PGT_writeable_page | PGT_validated | 1;   \
   40.64 +        (_pfn)->u.inuse.type_info  = PGT_writeable_page | PGT_validated | 1;\
   40.65          wmb(); /* install valid domain ptr before updating refcnt. */       \
   40.66          spin_lock(&(_dom)->page_alloc_lock);                                \
   40.67          /* _dom holds an allocation reference */                            \
   40.68 -        (_pfn)->count_and_flags = PGC_allocated | 1;                        \
   40.69 +        (_pfn)->u.inuse.count_info = PGC_allocated | 1;                     \
   40.70          if ( unlikely((_dom)->xenheap_pages++ == 0) )                       \
   40.71              get_domain(_dom);                                               \
   40.72          spin_unlock(&(_dom)->page_alloc_lock);                              \
   40.73 @@ -91,39 +111,32 @@ struct pfn_info
   40.74  
   40.75  extern struct pfn_info *frame_table;
   40.76  extern unsigned long frame_table_size;
   40.77 -extern struct list_head free_list;
   40.78 -extern spinlock_t free_list_lock;
   40.79 -extern unsigned int free_pfns;
   40.80  extern unsigned long max_page;
   40.81  void init_frametable(void *frametable_vstart, unsigned long nr_pages);
   40.82 -void add_to_domain_alloc_list(unsigned long ps, unsigned long pe);
   40.83 -
   40.84 -struct pfn_info *alloc_domain_page(struct domain *p);
   40.85 -void free_domain_page(struct pfn_info *page);
   40.86  
   40.87  int alloc_page_type(struct pfn_info *page, unsigned int type);
   40.88  void free_page_type(struct pfn_info *page, unsigned int type);
   40.89  
   40.90  static inline void put_page(struct pfn_info *page)
   40.91  {
   40.92 -    u32 nx, x, y = page->count_and_flags;
   40.93 +    u32 nx, x, y = page->u.inuse.count_info;
   40.94  
   40.95      do {
   40.96          x  = y;
   40.97          nx = x - 1;
   40.98      }
   40.99 -    while ( unlikely((y = cmpxchg(&page->count_and_flags, x, nx)) != x) );
  40.100 +    while ( unlikely((y = cmpxchg(&page->u.inuse.count_info, x, nx)) != x) );
  40.101  
  40.102      if ( unlikely((nx & PGC_count_mask) == 0) )
  40.103 -        free_domain_page(page);
  40.104 +        free_domheap_page(page);
  40.105  }
  40.106  
  40.107  
  40.108  static inline int get_page(struct pfn_info *page,
  40.109                             struct domain *domain)
  40.110  {
  40.111 -    u32 x, nx, y = page->count_and_flags;
  40.112 -    struct domain *p, *np = page->u.domain;
  40.113 +    u32 x, nx, y = page->u.inuse.count_info;
  40.114 +    struct domain *p, *np = page->u.inuse.domain;
  40.115  
  40.116      do {
  40.117          x  = y;
  40.118 @@ -137,13 +150,13 @@ static inline int get_page(struct pfn_in
  40.119                      " caf=%08x, taf=%08x\n",
  40.120                      page_to_pfn(page), domain, domain->domain,
  40.121                      p, (p && !((x & PGC_count_mask) == 0))?p->domain:999, 
  40.122 -                    x, page->type_and_flags);
  40.123 +                    x, page->u.inuse.type_info);
  40.124              return 0;
  40.125          }
  40.126          __asm__ __volatile__(
  40.127              LOCK_PREFIX "cmpxchg8b %3"
  40.128              : "=a" (np), "=d" (y), "=b" (p),
  40.129 -              "=m" (*(volatile u64 *)(&page->u.domain))
  40.130 +              "=m" (*(volatile u64 *)(&page->u.inuse.domain))
  40.131              : "0" (p), "1" (x), "b" (p), "c" (nx) );
  40.132      }
  40.133      while ( unlikely(np != p) || unlikely(y != x) );
  40.134 @@ -154,7 +167,7 @@ static inline int get_page(struct pfn_in
  40.135  
  40.136  static inline void put_page_type(struct pfn_info *page)
  40.137  {
  40.138 -    u32 nx, x, y = page->type_and_flags;
  40.139 +    u32 nx, x, y = page->u.inuse.type_info;
  40.140  
  40.141   again:
  40.142      do {
  40.143 @@ -171,7 +184,7 @@ static inline void put_page_type(struct 
  40.144                   * 'free' is safe because the refcnt is non-zero and the
  40.145                   * validated bit is clear => other ops will spin or fail.
  40.146                   */
  40.147 -                if ( unlikely((y = cmpxchg(&page->type_and_flags, x, 
  40.148 +                if ( unlikely((y = cmpxchg(&page->u.inuse.type_info, x, 
  40.149                                             x & ~PGT_validated)) != x) )
  40.150                      goto again;
  40.151                  /* We cleared the 'valid bit' so we must do the clear up. */
  40.152 @@ -182,13 +195,13 @@ static inline void put_page_type(struct 
  40.153              }
  40.154          }
  40.155      }
  40.156 -    while ( unlikely((y = cmpxchg(&page->type_and_flags, x, nx)) != x) );
  40.157 +    while ( unlikely((y = cmpxchg(&page->u.inuse.type_info, x, nx)) != x) );
  40.158  }
  40.159  
  40.160  
  40.161  static inline int get_page_type(struct pfn_info *page, u32 type)
  40.162  {
  40.163 -    u32 nx, x, y = page->type_and_flags;
  40.164 +    u32 nx, x, y = page->u.inuse.type_info;
  40.165   again:
  40.166      do {
  40.167          x  = y;
  40.168 @@ -218,7 +231,7 @@ static inline int get_page_type(struct p
  40.169          else if ( unlikely(!(x & PGT_validated)) )
  40.170          {
  40.171              /* Someone else is updating validation of this page. Wait... */
  40.172 -            while ( (y = page->type_and_flags) != x )
  40.173 +            while ( (y = page->u.inuse.type_info) != x )
  40.174              {
  40.175                  rep_nop();
  40.176                  barrier();
  40.177 @@ -226,7 +239,7 @@ static inline int get_page_type(struct p
  40.178              goto again;
  40.179          }
  40.180      }
  40.181 -    while ( unlikely((y = cmpxchg(&page->type_and_flags, x, nx)) != x) );
  40.182 +    while ( unlikely((y = cmpxchg(&page->u.inuse.type_info, x, nx)) != x) );
  40.183  
  40.184      if ( unlikely(!(nx & PGT_validated)) )
  40.185      {
  40.186 @@ -238,7 +251,7 @@ static inline int get_page_type(struct p
  40.187              put_page_type(page);
  40.188              return 0;
  40.189          }
  40.190 -        set_bit(_PGT_validated, &page->type_and_flags);
  40.191 +        set_bit(_PGT_validated, &page->u.inuse.type_info);
  40.192      }
  40.193  
  40.194      return 1;
  40.195 @@ -267,12 +280,12 @@ static inline int get_page_and_type(stru
  40.196      return rc;
  40.197  }
  40.198  
  40.199 -#define ASSERT_PAGE_IS_TYPE(_p, _t)                \
  40.200 -    ASSERT(((_p)->type_and_flags & PGT_type_mask) == (_t));  \
  40.201 -    ASSERT(((_p)->type_and_flags & PGT_count_mask) != 0)
  40.202 -#define ASSERT_PAGE_IS_DOMAIN(_p, _d)              \
  40.203 -    ASSERT(((_p)->count_and_flags & PGC_count_mask) != 0);  \
  40.204 -    ASSERT((_p)->u.domain == (_d))
  40.205 +#define ASSERT_PAGE_IS_TYPE(_p, _t)                            \
  40.206 +    ASSERT(((_p)->u.inuse.type_info & PGT_type_mask) == (_t)); \
  40.207 +    ASSERT(((_p)->u.inuse.type_info & PGT_count_mask) != 0)
  40.208 +#define ASSERT_PAGE_IS_DOMAIN(_p, _d)                          \
  40.209 +    ASSERT(((_p)->u.inuse.count_info & PGC_count_mask) != 0);  \
  40.210 +    ASSERT((_p)->u.inuse.domain == (_d))
  40.211  
  40.212  int check_descriptor(unsigned long *d);
  40.213  
    41.1 --- a/xen/include/asm-x86/page.h	Wed Jul 28 13:45:22 2004 +0000
    41.2 +++ b/xen/include/asm-x86/page.h	Wed Jul 28 13:48:19 2004 +0000
    41.3 @@ -102,6 +102,7 @@ typedef struct { unsigned long pt_lo; } 
    41.4  #define __pa(x)			((unsigned long)(x)-PAGE_OFFSET)
    41.5  #define __va(x)			((void *)((unsigned long)(x)+PAGE_OFFSET))
    41.6  #define page_address(_p)        (__va(((_p) - frame_table) << PAGE_SHIFT))
    41.7 +#define phys_to_page(kaddr)     (frame_table + ((kaddr) >> PAGE_SHIFT))
    41.8  #define virt_to_page(kaddr)	(frame_table + (__pa(kaddr) >> PAGE_SHIFT))
    41.9  #define VALID_PAGE(page)	((page - frame_table) < max_mapnr)
   41.10  
    42.1 --- a/xen/include/asm-x86/shadow.h	Wed Jul 28 13:45:22 2004 +0000
    42.2 +++ b/xen/include/asm-x86/shadow.h	Wed Jul 28 13:48:19 2004 +0000
    42.3 @@ -120,9 +120,9 @@ static inline int __mark_dirty( struct m
    42.4          SH_LOG("mark_dirty OOR! mfn=%x pfn=%x max=%x (mm %p)",
    42.5                 mfn, pfn, m->shadow_dirty_bitmap_size, m );
    42.6          SH_LOG("dom=%u caf=%08x taf=%08x\n", 
    42.7 -               frame_table[mfn].u.domain->domain,
    42.8 -               frame_table[mfn].count_and_flags, 
    42.9 -               frame_table[mfn].type_and_flags );
   42.10 +               frame_table[mfn].u.inuse.domain->domain,
   42.11 +               frame_table[mfn].u.inuse.count_info, 
   42.12 +               frame_table[mfn].u.inuse.type_info );
   42.13      }
   42.14  
   42.15      return rc;
    43.1 --- a/xen/include/xen/mm.h	Wed Jul 28 13:45:22 2004 +0000
    43.2 +++ b/xen/include/xen/mm.h	Wed Jul 28 13:48:19 2004 +0000
    43.3 @@ -2,13 +2,31 @@
    43.4  #ifndef __XEN_MM_H__
    43.5  #define __XEN_MM_H__
    43.6  
    43.7 -/* page_alloc.c */
    43.8 -void init_page_allocator(unsigned long min, unsigned long max);
    43.9 +struct domain;
   43.10 +struct pfn_info;
   43.11 +
   43.12 +/* Generic allocator */
   43.13 +unsigned long init_heap_allocator(
   43.14 +    unsigned long bitmap_start, unsigned long max_pages);
   43.15 +void init_heap_pages(int zone, struct pfn_info *pg, unsigned long nr_pages);
   43.16 +struct pfn_info *alloc_heap_pages(int zone, int order);
   43.17 +void free_heap_pages(int zone, struct pfn_info *pg, int order);
   43.18 +
   43.19 +/* Xen suballocator */
   43.20 +void init_xenheap_pages(unsigned long ps, unsigned long pe);
   43.21  unsigned long alloc_xenheap_pages(int order);
   43.22  void free_xenheap_pages(unsigned long p, int order);
   43.23  #define alloc_xenheap_page() (alloc_xenheap_pages(0))
   43.24  #define free_xenheap_page(_p) (free_xenheap_pages(_p,0))
   43.25  
   43.26 +/* Domain suballocator */
   43.27 +void init_domheap_pages(unsigned long ps, unsigned long pe);
   43.28 +struct pfn_info *alloc_domheap_pages(struct domain *d, int order);
   43.29 +void free_domheap_pages(struct pfn_info *pg, int order);
   43.30 +unsigned long avail_domheap_pages(void);
   43.31 +#define alloc_domheap_page(_d) (alloc_domheap_pages(_d,0))
   43.32 +#define free_domheap_page(_p) (free_domheap_pages(_p,0))
   43.33 +
   43.34  #include <asm/mm.h>
   43.35  
   43.36  #endif /* __XEN_MM_H__ */
    44.1 --- a/xen/include/xen/sched-if.h	Wed Jul 28 13:45:22 2004 +0000
    44.2 +++ b/xen/include/xen/sched-if.h	Wed Jul 28 13:48:19 2004 +0000
    44.3 @@ -11,8 +11,10 @@
    44.4  
    44.5  typedef struct schedule_data_st
    44.6  {
    44.7 -    struct domain *curr;           /* current task */
    44.8 -    struct domain *idle;           /* idle task for this cpu */
    44.9 +    spinlock_t          schedule_lock;  /* spinlock protecting curr pointer
   44.10 +                                            TODO check this */
   44.11 +    struct domain       *curr;          /* current task */
   44.12 +    struct domain       *idle;          /* idle task for this cpu */
   44.13      void *              sched_priv;
   44.14      struct ac_timer     s_timer;        /* scheduling timer  */
   44.15  #ifdef BUCKETS
    45.1 --- a/xen/include/xen/sched.h	Wed Jul 28 13:45:22 2004 +0000
    45.2 +++ b/xen/include/xen/sched.h	Wed Jul 28 13:48:19 2004 +0000
    45.3 @@ -196,8 +196,6 @@ void new_thread(struct domain *d,
    45.4  extern unsigned long wait_init_idle;
    45.5  #define init_idle() clear_bit(smp_processor_id(), &wait_init_idle);
    45.6  
    45.7 -extern spinlock_t schedule_lock[NR_CPUS] __cacheline_aligned;
    45.8 -
    45.9  #define set_current_state(_s) do { current->state = (_s); } while (0)
   45.10  void scheduler_init(void);
   45.11  void schedulers_start(void);