ia64/xen-unstable

changeset 1227:53a93ee1224d

bitkeeper revision 1.827 (4062f482Cd9Dl1Z7ZYy0WJkJfqr-qQ)

Merge tetris.cl.cam.ac.uk:/auto/homes/maw48/xen-syncpause.bk
into tetris.cl.cam.ac.uk:/auto/groups/xeno/users/iap10/xeno-clone/xeno.bk
author iap10@tetris.cl.cam.ac.uk
date Thu Mar 25 15:02:26 2004 +0000 (2004-03-25)
parents d19b6a99967b 201765d1eb87
children bf4b11f253d4
files .rootkeys BitKeeper/etc/ignore tools/misc/xen-clone tools/xc/lib/xc.h tools/xc/lib/xc_evtchn.c tools/xc/lib/xc_linux_build.c tools/xc/lib/xc_netbsd_build.c tools/xc/py/Xc.c tools/xend/lib/main.py tools/xend/lib/utils.c xen/arch/i386/Rules.mk xen/arch/i386/domain_page.c xen/arch/i386/entry.S xen/arch/i386/process.c xen/arch/i386/traps.c xen/common/debug.c xen/common/dom0_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/perfc.c xen/common/physdev.c xen/common/schedule.c xen/common/shadow.c xen/drivers/block/xen_block.c xen/drivers/block/xen_vbd.c xen/drivers/char/console.c xen/drivers/char/keyboard.c xen/include/asm-i386/config.h xen/include/asm-i386/page.h xen/include/asm-i386/processor.h xen/include/hypervisor-ifs/dom0_ops.h xen/include/hypervisor-ifs/event_channel.h xen/include/hypervisor-ifs/hypervisor-if.h xen/include/xen/event.h xen/include/xen/mm.h xen/include/xen/perfc.h xen/include/xen/perfc_defn.h xen/include/xen/sched.h xen/include/xen/shadow.h xen/net/dev.c xenolinux-2.4.25-sparse/arch/xen/drivers/block/block.c xenolinux-2.4.25-sparse/arch/xen/drivers/console/console.c xenolinux-2.4.25-sparse/arch/xen/drivers/evtchn/evtchn.c xenolinux-2.4.25-sparse/arch/xen/drivers/network/network.c xenolinux-2.4.25-sparse/arch/xen/drivers/vnetif/vnetif.c xenolinux-2.4.25-sparse/arch/xen/kernel/Makefile xenolinux-2.4.25-sparse/arch/xen/kernel/entry.S xenolinux-2.4.25-sparse/arch/xen/kernel/evtchn.c xenolinux-2.4.25-sparse/arch/xen/kernel/hypervisor.c xenolinux-2.4.25-sparse/arch/xen/kernel/i386_ksyms.c xenolinux-2.4.25-sparse/arch/xen/kernel/physirq.c xenolinux-2.4.25-sparse/arch/xen/kernel/setup.c xenolinux-2.4.25-sparse/arch/xen/kernel/time.c xenolinux-2.4.25-sparse/include/asm-xen/evtchn.h xenolinux-2.4.25-sparse/include/asm-xen/hypervisor.h xenolinux-2.4.25-sparse/include/asm-xen/irq.h xenolinux-2.4.25-sparse/include/asm-xen/keyboard.h xenolinux-2.4.25-sparse/include/asm-xen/system.h
line diff
     1.1 --- a/.rootkeys	Wed Mar 24 19:05:53 2004 +0000
     1.2 +++ b/.rootkeys	Thu Mar 25 15:02:26 2004 +0000
     1.3 @@ -178,6 +178,7 @@ 3ddb79bdHqdQpATqC0rmUZNbsb6L6A xen/commo
     1.4  40589968dD2D1aejwSOvrROg7fOvGQ xen/common/sched_bvt.c
     1.5  40589968be_t_n0-w6ggceW7h-sx0w xen/common/sched_rrobin.c
     1.6  3e397e6619PgAfBbw2XFbXkewvUWgw xen/common/schedule.c
     1.7 +405b8599xI_PoEr3zZoJ2on-jdn7iw xen/common/shadow.c
     1.8  3ddb79bdB9RNMnkQnUyZ5C9hhMSQQw xen/common/slab.c
     1.9  3ddb79bd0gVQYmL2zvuJnldvD0AGxQ xen/common/softirq.c
    1.10  3e7f358awXBC3Vw-wFRwPw18qL1khg xen/common/string.c
    1.11 @@ -574,6 +575,7 @@ 3e4540ccU1sgCx8seIMGlahmMfv7yQ xen/inclu
    1.12  40589969nPq3DMzv24RDb5LXE9brHw xen/include/xen/sched-if.h
    1.13  3ddb79c0LzqqS0LhAQ50ekgj4oGl7Q xen/include/xen/sched.h
    1.14  403a06a7H0hpHcKpAiDe5BPnaXWTlA xen/include/xen/serial.h
    1.15 +405b8599BsDsDwKEJLS0XipaiQW3TA xen/include/xen/shadow.h
    1.16  3ddb79c0VDeD-Oft5eNfMneTU3D1dQ xen/include/xen/skbuff.h
    1.17  3ddb79c14dXIhP7C2ahnoD08K90G_w xen/include/xen/slab.h
    1.18  3ddb79c09xbS-xxfKxuV3JETIhBzmg xen/include/xen/smp.h
    1.19 @@ -628,8 +630,8 @@ 405853f2wg7JXZJNltspMwOZJklxgw xenolinux
    1.20  405853f6nbeazrNyEWNHBuoSg2PiPA xenolinux-2.4.25-sparse/arch/xen/drivers/vnetif/vnetif.c
    1.21  3e5a4e65lWzkiPXsZdzPt2RNnJGG1g xenolinux-2.4.25-sparse/arch/xen/kernel/Makefile
    1.22  3e5a4e65_hqfuxtGG8IUy6wRM86Ecg xenolinux-2.4.25-sparse/arch/xen/kernel/entry.S
    1.23 +3e5a4e65ibVQmwlOn0j3sVH_j_6hAg xenolinux-2.4.25-sparse/arch/xen/kernel/evtchn.c
    1.24  3e5a4e65Hy_1iUvMTPsNqGNXd9uFpg xenolinux-2.4.25-sparse/arch/xen/kernel/head.S
    1.25 -3e5a4e65ibVQmwlOn0j3sVH_j_6hAg xenolinux-2.4.25-sparse/arch/xen/kernel/hypervisor.c
    1.26  3e5a4e65RMGcuA-HCn3-wNx3fFQwdg xenolinux-2.4.25-sparse/arch/xen/kernel/i386_ksyms.c
    1.27  3e5a4e65MEvZhlr070sK5JsfAQlv7Q xenolinux-2.4.25-sparse/arch/xen/kernel/ioport.c
    1.28  3e5a4e653U6cELGv528IxOLHvCq8iA xenolinux-2.4.25-sparse/arch/xen/kernel/irq.c
     2.1 --- a/BitKeeper/etc/ignore	Wed Mar 24 19:05:53 2004 +0000
     2.2 +++ b/BitKeeper/etc/ignore	Thu Mar 25 15:02:26 2004 +0000
     2.3 @@ -1,27 +1,567 @@
     2.4 +*.a
     2.5 +*.o
     2.6 +*.pyc
     2.7 +*.so
     2.8 +*.so.*
     2.9  BitKeeper/*/*
    2.10  PENDING/*
    2.11 -*.o
    2.12 -*.so
    2.13 -*.so.*
    2.14 -*.a
    2.15 -*.pyc
    2.16 +TAGS
    2.17 +URK
    2.18  extras/mini-os/h/hypervisor-ifs
    2.19  tools/*/build/lib*/*.py
    2.20  tools/balloon/balloon
    2.21 +tools/control/.checkstyle
    2.22 +tools/control/.classpath
    2.23 +tools/control/.project
    2.24 +tools/control/build-cmdline/**
    2.25 +tools/control/build-dom/uk/ac/cam/cl/xeno/domctl/Command.class
    2.26 +tools/control/build-dom/uk/ac/cam/cl/xeno/domctl/CommandDestroy.class
    2.27 +tools/control/build-dom/uk/ac/cam/cl/xeno/domctl/CommandHelp.class
    2.28 +tools/control/build-dom/uk/ac/cam/cl/xeno/domctl/CommandList.class
    2.29 +tools/control/build-dom/uk/ac/cam/cl/xeno/domctl/CommandNew.class
    2.30 +tools/control/build-dom/uk/ac/cam/cl/xeno/domctl/CommandStart.class
    2.31 +tools/control/build-dom/uk/ac/cam/cl/xeno/domctl/CommandStop.class
    2.32 +tools/control/build-dom/uk/ac/cam/cl/xeno/domctl/Defaults$Handler.class
    2.33 +tools/control/build-dom/uk/ac/cam/cl/xeno/domctl/Defaults.class
    2.34 +tools/control/build-dom/uk/ac/cam/cl/xeno/domctl/Domain.class
    2.35 +tools/control/build-dom/uk/ac/cam/cl/xeno/domctl/InetAddressPattern.class
    2.36 +tools/control/build-dom/uk/ac/cam/cl/xeno/domctl/Main.class
    2.37 +tools/control/build-dom/uk/ac/cam/cl/xeno/domctl/Settings.class
    2.38 +tools/control/build-dom/uk/ac/cam/cl/xeno/domctl/StringPattern.class
    2.39 +tools/control/build-web/**
    2.40 +tools/control/build-xen/WEB-INF/classes/uk/ac/cam/cl/xeno/domctl/Command.class
    2.41 +tools/control/build-xen/WEB-INF/classes/uk/ac/cam/cl/xeno/domctl/CommandDestroy.class
    2.42 +tools/control/build-xen/WEB-INF/classes/uk/ac/cam/cl/xeno/domctl/CommandHelp.class
    2.43 +tools/control/build-xen/WEB-INF/classes/uk/ac/cam/cl/xeno/domctl/CommandList.class
    2.44 +tools/control/build-xen/WEB-INF/classes/uk/ac/cam/cl/xeno/domctl/CommandNew.class
    2.45 +tools/control/build-xen/WEB-INF/classes/uk/ac/cam/cl/xeno/domctl/CommandStart.class
    2.46 +tools/control/build-xen/WEB-INF/classes/uk/ac/cam/cl/xeno/domctl/CommandStop.class
    2.47 +tools/control/build-xen/WEB-INF/classes/uk/ac/cam/cl/xeno/domctl/Defaults$Handler.class
    2.48 +tools/control/build-xen/WEB-INF/classes/uk/ac/cam/cl/xeno/domctl/Defaults.class
    2.49 +tools/control/build-xen/WEB-INF/classes/uk/ac/cam/cl/xeno/domctl/Domain.class
    2.50 +tools/control/build-xen/WEB-INF/classes/uk/ac/cam/cl/xeno/domctl/InetAddressPattern.class
    2.51 +tools/control/build-xen/WEB-INF/classes/uk/ac/cam/cl/xeno/domctl/Main.class
    2.52 +tools/control/build-xen/WEB-INF/classes/uk/ac/cam/cl/xeno/domctl/Settings.class
    2.53 +tools/control/build-xen/WEB-INF/classes/uk/ac/cam/cl/xeno/domctl/StringPattern.class
    2.54 +tools/control/build-xen/WEB-INF/classes/uk/ac/cam/cl/xeno/xenctl/Extent.class
    2.55 +tools/control/build-xen/WEB-INF/classes/uk/ac/cam/cl/xeno/xenctl/Library.class
    2.56 +tools/control/build-xen/WEB-INF/classes/uk/ac/cam/cl/xeno/xenctl/Main.java.orig
    2.57 +tools/control/build-xen/WEB-INF/classes/uk/ac/cam/cl/xeno/xenctl/Mode.class
    2.58 +tools/control/build-xen/WEB-INF/classes/uk/ac/cam/cl/xeno/xenctl/Parser.class
    2.59 +tools/control/build-xen/WEB-INF/classes/uk/ac/cam/cl/xeno/xenctl/Partition.class
    2.60 +tools/control/build-xen/WEB-INF/classes/uk/ac/cam/cl/xeno/xenctl/PartitionManager.class
    2.61 +tools/control/build-xen/WEB-INF/classes/uk/ac/cam/cl/xeno/xenctl/RootBean.class
    2.62 +tools/control/build-xen/WEB-INF/classes/uk/ac/cam/cl/xeno/xenctl/SystemConfigurationBean.class
    2.63 +tools/control/build-xen/WEB-INF/classes/uk/ac/cam/cl/xeno/xenctl/VirtualBlockDevice.class
    2.64 +tools/control/build-xen/WEB-INF/classes/uk/ac/cam/cl/xeno/xenctl/VirtualDisk.class
    2.65 +tools/control/build-xen/WEB-INF/classes/uk/ac/cam/cl/xeno/xenctl/VirtualDiskManager.class
    2.66 +tools/control/build-xen/WEB-INF/classes/uk/ac/cam/cl/xeno/xenctl/XML.class
    2.67 +tools/control/build-xen/WEB-INF/classes/uk/ac/cam/cl/xeno/xenctl/XMLHelper.class
    2.68 +tools/control/build-xen/WEB-INF/web.xml
    2.69 +tools/control/build-xen/about.jsp
    2.70 +tools/control/build-xen/dom-del.jsp
    2.71 +tools/control/build-xen/dom-delr.jsp
    2.72 +tools/control/build-xen/dom-lis.jsp
    2.73 +tools/control/build-xen/dom-new.jsp
    2.74 +tools/control/build-xen/dom-newr.jsp
    2.75 +tools/control/build-xen/dom-sta.jsp
    2.76 +tools/control/build-xen/dom-star.jsp
    2.77 +tools/control/build-xen/dom-stp.jsp
    2.78 +tools/control/build-xen/dom-stpr.jsp
    2.79 +tools/control/build-xen/dom.jsp
    2.80 +tools/control/build-xen/help.jsp
    2.81 +tools/control/build-xen/img/cambridge.gif
    2.82 +tools/control/build-xen/img/help.gif
    2.83 +tools/control/build-xen/img/home.gif
    2.84 +tools/control/build-xen/img/pixel.gif
    2.85 +tools/control/build-xen/img/search.gif
    2.86 +tools/control/build-xen/img/xeno.gif
    2.87 +tools/control/build-xen/index.jsp
    2.88 +tools/control/build-xen/newdom.jsp
    2.89 +tools/control/build-xen/tmpl/about.tmpl
    2.90 +tools/control/build-xen/tmpl/dom-del.tmpl
    2.91 +tools/control/build-xen/tmpl/dom-delr.tmpl
    2.92 +tools/control/build-xen/tmpl/dom-lis.tmpl
    2.93 +tools/control/build-xen/tmpl/dom-new.tmpl
    2.94 +tools/control/build-xen/tmpl/dom-newr.tmpl
    2.95 +tools/control/build-xen/tmpl/dom-sta.tmpl
    2.96 +tools/control/build-xen/tmpl/dom-star.tmpl
    2.97 +tools/control/build-xen/tmpl/dom-stp.tmpl
    2.98 +tools/control/build-xen/tmpl/dom-stpr.tmpl
    2.99 +tools/control/build-xen/tmpl/dom.tmpl
   2.100 +tools/control/build-xen/tmpl/dommenu.tmpl
   2.101 +tools/control/build-xen/tmpl/help.tmpl
   2.102 +tools/control/build-xen/tmpl/index.tmpl
   2.103 +tools/control/build-xen/tmpl/install.pl
   2.104 +tools/control/build-xen/tmpl/makefile
   2.105 +tools/control/build-xen/tmpl/newdom.tmpl
   2.106 +tools/control/build-xen/tmpl/vd-fv.tmpl
   2.107 +tools/control/build-xen/tmpl/vd-pa.tmpl
   2.108 +tools/control/build-xen/tmpl/vd-par.tmpl
   2.109 +tools/control/build-xen/tmpl/vd-pv.tmpl
   2.110 +tools/control/build-xen/tmpl/vd-vbdc.tmpl
   2.111 +tools/control/build-xen/tmpl/vd-vbdcr.tmpl
   2.112 +tools/control/build-xen/tmpl/vd-vbdd.tmpl
   2.113 +tools/control/build-xen/tmpl/vd-vbdf.tmpl
   2.114 +tools/control/build-xen/tmpl/vd-vbdfr.tmpl
   2.115 +tools/control/build-xen/tmpl/vd-vbdv.tmpl
   2.116 +tools/control/build-xen/tmpl/vd-vdc.tmpl
   2.117 +tools/control/build-xen/tmpl/vd-vdcr.tmpl
   2.118 +tools/control/build-xen/tmpl/vd-vdd.tmpl
   2.119 +tools/control/build-xen/tmpl/vd-vddr.tmpl
   2.120 +tools/control/build-xen/tmpl/vd-vdr.tmpl
   2.121 +tools/control/build-xen/tmpl/vd-vdrr.tmpl
   2.122 +tools/control/build-xen/tmpl/vd-vdv.tmpl
   2.123 +tools/control/build-xen/tmpl/vd.tmpl
   2.124 +tools/control/build-xen/tmpl/vdmenu.tmpl
   2.125 +tools/control/build-xen/tmpl/xenofoot.def
   2.126 +tools/control/build-xen/tmpl/xenohead.def
   2.127 +tools/control/build-xen/tmpl/xenostyle.css
   2.128 +tools/control/build-xen/vd-fv.jsp
   2.129 +tools/control/build-xen/vd-pa.jsp
   2.130 +tools/control/build-xen/vd-par.jsp
   2.131 +tools/control/build-xen/vd-pv.jsp
   2.132 +tools/control/build-xen/vd-vbdc.jsp
   2.133 +tools/control/build-xen/vd-vbdcr.jsp
   2.134 +tools/control/build-xen/vd-vbdd.jsp
   2.135 +tools/control/build-xen/vd-vbdf.jsp
   2.136 +tools/control/build-xen/vd-vbdfr.jsp
   2.137 +tools/control/build-xen/vd-vbdv.jsp
   2.138 +tools/control/build-xen/vd-vdc.jsp
   2.139 +tools/control/build-xen/vd-vdcr.jsp
   2.140 +tools/control/build-xen/vd-vdd.jsp
   2.141 +tools/control/build-xen/vd-vddr.jsp
   2.142 +tools/control/build-xen/vd-vdr.jsp
   2.143 +tools/control/build-xen/vd-vdrr.jsp
   2.144 +tools/control/build-xen/vd-vdv.jsp
   2.145 +tools/control/build-xen/vd.jsp
   2.146 +tools/control/build-xen/xenostyle.css
   2.147 +tools/control/dist-web/**
   2.148 +tools/control/dist/docs/api/allclasses-frame.html
   2.149 +tools/control/dist/docs/api/allclasses-noframe.html
   2.150 +tools/control/dist/docs/api/constant-values.html
   2.151 +tools/control/dist/docs/api/deprecated-list.html
   2.152 +tools/control/dist/docs/api/help-doc.html
   2.153 +tools/control/dist/docs/api/index-all.html
   2.154 +tools/control/dist/docs/api/index.html
   2.155 +tools/control/dist/docs/api/overview-frame.html
   2.156 +tools/control/dist/docs/api/overview-summary.html
   2.157 +tools/control/dist/docs/api/overview-tree.html
   2.158 +tools/control/dist/docs/api/package-list
   2.159 +tools/control/dist/docs/api/packages.html
   2.160 +tools/control/dist/docs/api/stylesheet.css
   2.161 +tools/control/dist/docs/api/uk/ac/cam/cl/xeno/domctl/Command.html
   2.162 +tools/control/dist/docs/api/uk/ac/cam/cl/xeno/domctl/CommandDestroy.html
   2.163 +tools/control/dist/docs/api/uk/ac/cam/cl/xeno/domctl/CommandHelp.html
   2.164 +tools/control/dist/docs/api/uk/ac/cam/cl/xeno/domctl/CommandList.html
   2.165 +tools/control/dist/docs/api/uk/ac/cam/cl/xeno/domctl/CommandNew.html
   2.166 +tools/control/dist/docs/api/uk/ac/cam/cl/xeno/domctl/CommandStart.html
   2.167 +tools/control/dist/docs/api/uk/ac/cam/cl/xeno/domctl/CommandStop.html
   2.168 +tools/control/dist/docs/api/uk/ac/cam/cl/xeno/domctl/Defaults.html
   2.169 +tools/control/dist/docs/api/uk/ac/cam/cl/xeno/domctl/Domain.html
   2.170 +tools/control/dist/docs/api/uk/ac/cam/cl/xeno/domctl/InetAddressPattern.html
   2.171 +tools/control/dist/docs/api/uk/ac/cam/cl/xeno/domctl/Main.html
   2.172 +tools/control/dist/docs/api/uk/ac/cam/cl/xeno/domctl/Settings.html
   2.173 +tools/control/dist/docs/api/uk/ac/cam/cl/xeno/domctl/StringPattern.html
   2.174 +tools/control/dist/docs/api/uk/ac/cam/cl/xeno/domctl/package-frame.html
   2.175 +tools/control/dist/docs/api/uk/ac/cam/cl/xeno/domctl/package-summary.html
   2.176 +tools/control/dist/docs/api/uk/ac/cam/cl/xeno/domctl/package-tree.html
   2.177 +tools/control/dist/docs/api/uk/ac/cam/cl/xeno/xenctl/Extent.html
   2.178 +tools/control/dist/docs/api/uk/ac/cam/cl/xeno/xenctl/Library.html
   2.179 +tools/control/dist/docs/api/uk/ac/cam/cl/xeno/xenctl/Mode.html
   2.180 +tools/control/dist/docs/api/uk/ac/cam/cl/xeno/xenctl/Parser.html
   2.181 +tools/control/dist/docs/api/uk/ac/cam/cl/xeno/xenctl/Partition.html
   2.182 +tools/control/dist/docs/api/uk/ac/cam/cl/xeno/xenctl/PartitionManager.html
   2.183 +tools/control/dist/docs/api/uk/ac/cam/cl/xeno/xenctl/RootBean.html
   2.184 +tools/control/dist/docs/api/uk/ac/cam/cl/xeno/xenctl/SystemConfigurationBean.html
   2.185 +tools/control/dist/docs/api/uk/ac/cam/cl/xeno/xenctl/VirtualBlockDevice.html
   2.186 +tools/control/dist/docs/api/uk/ac/cam/cl/xeno/xenctl/VirtualDisk.html
   2.187 +tools/control/dist/docs/api/uk/ac/cam/cl/xeno/xenctl/VirtualDiskManager.html
   2.188 +tools/control/dist/docs/api/uk/ac/cam/cl/xeno/xenctl/XML.html
   2.189 +tools/control/dist/docs/api/uk/ac/cam/cl/xeno/xenctl/XMLHelper.html
   2.190 +tools/control/dist/docs/api/uk/ac/cam/cl/xeno/xenctl/package-frame.html
   2.191 +tools/control/dist/docs/api/uk/ac/cam/cl/xeno/xenctl/package-summary.html
   2.192 +tools/control/dist/docs/api/uk/ac/cam/cl/xeno/xenctl/package-tree.html
   2.193 +tools/control/dist/docs/empty_dir
   2.194 +tools/control/dist/xenctl-0.1-dev.war
   2.195 +tools/control/domctl.jar
   2.196 +tools/control/eclipsebin/**
   2.197 +tools/control/web/about.jsp
   2.198 +tools/control/web/dom-del.jsp
   2.199 +tools/control/web/dom-delr.jsp
   2.200 +tools/control/web/dom-lis.jsp
   2.201 +tools/control/web/dom-new.jsp
   2.202 +tools/control/web/dom-newr.jsp
   2.203 +tools/control/web/dom-sta.jsp
   2.204 +tools/control/web/dom-star.jsp
   2.205 +tools/control/web/dom-stp.jsp
   2.206 +tools/control/web/dom-stpr.jsp
   2.207 +tools/control/web/dom.jsp
   2.208 +tools/control/web/help.jsp
   2.209 +tools/control/web/index.jsp
   2.210 +tools/control/web/newdom.jsp
   2.211 +tools/control/web/pd-g.jsp
   2.212 +tools/control/web/pd-gr.jsp
   2.213 +tools/control/web/pd-l.jsp
   2.214 +tools/control/web/pd-r.jsp
   2.215 +tools/control/web/pd-rr.jsp
   2.216 +tools/control/web/pd.jsp
   2.217 +tools/control/web/vd-fv.jsp
   2.218 +tools/control/web/vd-pa.jsp
   2.219 +tools/control/web/vd-par.jsp
   2.220 +tools/control/web/vd-pv.jsp
   2.221 +tools/control/web/vd-vbdc.jsp
   2.222 +tools/control/web/vd-vbdcr.jsp
   2.223 +tools/control/web/vd-vbdd.jsp
   2.224 +tools/control/web/vd-vbdf.jsp
   2.225 +tools/control/web/vd-vbdfr.jsp
   2.226 +tools/control/web/vd-vbdv.jsp
   2.227 +tools/control/web/vd-vdc.jsp
   2.228 +tools/control/web/vd-vdcr.jsp
   2.229 +tools/control/web/vd-vdd.jsp
   2.230 +tools/control/web/vd-vddr.jsp
   2.231 +tools/control/web/vd-vdr.jsp
   2.232 +tools/control/web/vd-vdrr.jsp
   2.233 +tools/control/web/vd-vdv.jsp
   2.234 +tools/control/web/vd.jsp
   2.235 +tools/control/web/xenostyle.css
   2.236 +tools/control/xenctl-cmdline.jar
   2.237 +tools/domain_builder/dom_builder.o
   2.238 +tools/domain_builder/dom_kill.o
   2.239 +tools/domain_builder/domain_builder
   2.240 +tools/domain_builder/kill_domain
   2.241 +tools/domctl/build/uk/ac/cam/cl/xeno/domctl/Command.class
   2.242 +tools/domctl/build/uk/ac/cam/cl/xeno/domctl/CommandDestroy.class
   2.243 +tools/domctl/build/uk/ac/cam/cl/xeno/domctl/CommandHelp.class
   2.244 +tools/domctl/build/uk/ac/cam/cl/xeno/domctl/CommandNew.class
   2.245 +tools/domctl/build/uk/ac/cam/cl/xeno/domctl/CommandStart.class
   2.246 +tools/domctl/build/uk/ac/cam/cl/xeno/domctl/CommandStop.class
   2.247 +tools/domctl/build/uk/ac/cam/cl/xeno/domctl/Defaults$Handler.class
   2.248 +tools/domctl/build/uk/ac/cam/cl/xeno/domctl/Defaults.class
   2.249 +tools/domctl/build/uk/ac/cam/cl/xeno/domctl/InetAddressPattern.class
   2.250 +tools/domctl/build/uk/ac/cam/cl/xeno/domctl/Main.class
   2.251 +tools/domctl/build/uk/ac/cam/cl/xeno/domctl/Settings.class
   2.252 +tools/domctl/build/uk/ac/cam/cl/xeno/domctl/StringPattern.class
   2.253 +tools/domctl/domctl.jar
   2.254 +tools/internal/xi_build
   2.255 +tools/internal/xi_build.o
   2.256 +tools/internal/xi_create
   2.257 +tools/internal/xi_create.o
   2.258 +tools/internal/xi_destroy
   2.259 +tools/internal/xi_destroy.o
   2.260 +tools/internal/xi_list
   2.261 +tools/internal/xi_phys_grant
   2.262 +tools/internal/xi_phys_grant.c~
   2.263 +tools/internal/xi_phys_grant.o
   2.264 +tools/internal/xi_phys_probe
   2.265 +tools/internal/xi_phys_probe.c~
   2.266 +tools/internal/xi_phys_probe.o
   2.267 +tools/internal/xi_phys_revoke
   2.268 +tools/internal/xi_phys_revoke.c~
   2.269 +tools/internal/xi_phys_revoke.o
   2.270 +tools/internal/xi_restore_linux
   2.271 +tools/internal/xi_save_linux
   2.272 +tools/internal/xi_sched_domain
   2.273 +tools/internal/xi_sched_global
   2.274 +tools/internal/xi_start
   2.275 +tools/internal/xi_start.o
   2.276 +tools/internal/xi_stop
   2.277 +tools/internal/xi_stop.o
   2.278 +tools/internal/xi_usage
   2.279 +tools/internal/xi_vbd_add
   2.280 +tools/internal/xi_vbd_create
   2.281 +tools/internal/xi_vbd_info
   2.282 +tools/internal/xi_vbd_list
   2.283 +tools/internal/xi_vif_params
   2.284  tools/misc/miniterm/miniterm
   2.285 -tools/misc/xen_read_console
   2.286  tools/misc/xen_cpuperf
   2.287  tools/misc/xen_log
   2.288 +tools/misc/xen_netwatch
   2.289 +tools/misc/xen_read_console
   2.290 +tools/misc/xen_refresh_dev
   2.291 +tools/vdmanager/build/uk/ac/cam/cl/xeno/vdmanager/Extent.class
   2.292 +tools/vdmanager/build/uk/ac/cam/cl/xeno/vdmanager/Library.class
   2.293 +tools/vdmanager/build/uk/ac/cam/cl/xeno/vdmanager/Main.class
   2.294 +tools/vdmanager/build/uk/ac/cam/cl/xeno/vdmanager/Mode.class
   2.295 +tools/vdmanager/build/uk/ac/cam/cl/xeno/vdmanager/Parser.class
   2.296 +tools/vdmanager/build/uk/ac/cam/cl/xeno/vdmanager/Partition.class
   2.297 +tools/vdmanager/build/uk/ac/cam/cl/xeno/vdmanager/PartitionManager.class
   2.298 +tools/vdmanager/build/uk/ac/cam/cl/xeno/vdmanager/VirtualBlockDevice.class
   2.299 +tools/vdmanager/build/uk/ac/cam/cl/xeno/vdmanager/VirtualDisk.class
   2.300 +tools/vdmanager/build/uk/ac/cam/cl/xeno/vdmanager/VirtualDiskManager.class
   2.301 +tools/vdmanager/build/uk/ac/cam/cl/xeno/vdmanager/XML.class
   2.302 +tools/vdmanager/build/uk/ac/cam/cl/xeno/vdmanager/XMLHelper.class
   2.303 +tools/vdmanager/vdmanager.jar
   2.304 +tools/xc/lib/libxc.a
   2.305 +tools/xc/lib/libxc.so
   2.306 +tools/xc/lib/libxc.so.1.3
   2.307 +tools/xc/lib/libxc.so.1.3.0
   2.308 +tools/xc/lib/libxc_bvtsched.o
   2.309 +tools/xc/lib/libxc_domain.o
   2.310 +tools/xc/lib/libxc_linux_build.o
   2.311 +tools/xc/lib/libxc_linux_restore.o
   2.312 +tools/xc/lib/libxc_linux_save.o
   2.313 +tools/xc/lib/libxc_misc.o
   2.314 +tools/xc/lib/libxc_private.o
   2.315 +tools/xc/lib/libxc_vbd.o
   2.316 +tools/xc/lib/libxc_vif.o
   2.317 +tools/xc/lib/xc_bvtsched.o
   2.318 +tools/xc/lib/xc_domain.o
   2.319 +tools/xc/lib/xc_evtchn.o
   2.320 +tools/xc/lib/xc_linux_build.o
   2.321 +tools/xc/lib/xc_linux_restore.o
   2.322 +tools/xc/lib/xc_linux_save.o
   2.323 +tools/xc/lib/xc_misc.o
   2.324 +tools/xc/lib/xc_netbsd_build.o
   2.325 +tools/xc/lib/xc_physdev.o
   2.326 +tools/xc/lib/xc_private.o
   2.327 +tools/xc/lib/xc_vbd.o
   2.328 +tools/xc/lib/xc_vif.o
   2.329 +tools/xc/py/XenoUtil.pyc
   2.330 +tools/xc/py/build/lib.linux-i686-2.2/Xc.so
   2.331 +tools/xc/py/build/lib/XenoUtil.py
   2.332 +tools/xc/py/build/temp.linux-i686-2.2/Xc.o
   2.333 +tools/xend/xend
   2.334 +tools/xend/xend.o
   2.335 +tools/xend/xend_utils.o
   2.336  tools/xentrace/xentrace
   2.337 +xen-2.4.16/common/domain.c.smh
   2.338 +xen-2.4.16/common/kernel.c.ok-ish
   2.339 +xen-2.4.16/common/kernel.c.old
   2.340 +xen-2.4.16/drivers/block/ll_rw_blk.c.orig
   2.341 +xen-2.4.16/drivers/ide/ide-disk.c.orig
   2.342 +xen-2.4.16/drivers/ide/ide-probe.c.orig
   2.343 +xen-2.4.16/drivers/ide/ide-taskfile.c.orig
   2.344 +xen-2.4.16/drivers/ide/ide.c.orig
   2.345 +xen-2.4.16/drivers/net/e1000/e1000.o
   2.346 +xen-2.4.16/drivers/net/e1000/e1000_ethtool.o
   2.347 +xen-2.4.16/drivers/net/e1000/e1000_hw.o
   2.348 +xen-2.4.16/drivers/net/e1000/e1000_main.o
   2.349 +xen-2.4.16/drivers/net/e1000/e1000_param.o
   2.350 +xen-2.4.16/foo
   2.351 +xen-2.4.16/include/hypervisor-ifs/block.h.orig
   2.352 +xen-2.4.16/include/xeno/blkdev.h.orig
   2.353 +xen-2.4.16/include/xeno/sched.h.orig
   2.354 +xen-2.4.16/size.image
   2.355 +xen/BLOG
   2.356 +xen/arch/i386/acpitable.o
   2.357 +xen/arch/i386/apic.o
   2.358 +xen/arch/i386/arch.o
   2.359 +xen/arch/i386/boot/boot.o
   2.360 +xen/arch/i386/delay.o
   2.361 +xen/arch/i386/entry.o
   2.362 +xen/arch/i386/extable.o
   2.363 +xen/arch/i386/flushtlb.o
   2.364 +xen/arch/i386/i387.o
   2.365 +xen/arch/i386/i8259.o
   2.366 +xen/arch/i386/idle0_task.o
   2.367 +xen/arch/i386/io_apic.o
   2.368 +xen/arch/i386/ioremap.o
   2.369 +xen/arch/i386/irq.o
   2.370 +xen/arch/i386/mm.o
   2.371 +xen/arch/i386/mpparse.o
   2.372 +xen/arch/i386/nmi.o
   2.373 +xen/arch/i386/pci-dma.o
   2.374 +xen/arch/i386/pci-i386.o
   2.375 +xen/arch/i386/pci-irq.o
   2.376 +xen/arch/i386/pci-pc.o
   2.377 +xen/arch/i386/pdb-stub.o
   2.378 +xen/arch/i386/process.o
   2.379 +xen/arch/i386/rwlock.o
   2.380 +xen/arch/i386/setup.o
   2.381 +xen/arch/i386/smp.o
   2.382 +xen/arch/i386/smpboot.o
   2.383 +xen/arch/i386/time.o
   2.384 +xen/arch/i386/trampoline.o
   2.385 +xen/arch/i386/traps.o
   2.386 +xen/arch/i386/usercopy.o
   2.387 +xen/common/ac_timer.o
   2.388 +xen/common/block.o
   2.389 +xen/common/brlock.o
   2.390 +xen/common/common.o
   2.391 +xen/common/console.o
   2.392 +xen/common/debug-linux.o
   2.393 +xen/common/debug.c~
   2.394 +xen/common/debug.o
   2.395 +xen/common/dom0_ops.o
   2.396 +xen/common/dom_mem_ops.o
   2.397 +xen/common/domain.o
   2.398 +xen/common/domain_page.o
   2.399 +xen/common/event.o
   2.400 +xen/common/event_channel.o
   2.401 +xen/common/kernel.o
   2.402 +xen/common/keyhandler.o
   2.403 +xen/common/lib.o
   2.404 +xen/common/memory.o
   2.405 +xen/common/network.o
   2.406 +xen/common/page_alloc.o
   2.407 +xen/common/perfc.o
   2.408 +xen/common/physdev.o
   2.409 +xen/common/rbtree.o
   2.410 +xen/common/resource.o
   2.411 +xen/common/schedule.o
   2.412 +xen/common/shadow.o
   2.413 +xen/common/slab.o
   2.414 +xen/common/softirq.o
   2.415 +xen/common/string.o
   2.416 +xen/common/timer.o
   2.417 +xen/common/trace.o
   2.418 +xen/common/vsprintf.o
   2.419 +xen/drivers/block/blkpg.o
   2.420 +xen/drivers/block/cciss.o
   2.421 +xen/drivers/block/cciss_scsi.o
   2.422 +xen/drivers/block/driver.o
   2.423 +xen/drivers/block/elevator.o
   2.424 +xen/drivers/block/genhd.o
   2.425 +xen/drivers/block/ll_rw_blk.o
   2.426 +xen/drivers/block/xen_block.c~
   2.427 +xen/drivers/block/xen_block.o
   2.428 +xen/drivers/block/xen_physdisk.c~
   2.429 +xen/drivers/block/xen_physdisk.o
   2.430 +xen/drivers/block/xen_segment.o
   2.431 +xen/drivers/block/xen_vbd.o
   2.432 +xen/drivers/cdrom/cdrom.o
   2.433 +xen/drivers/cdrom/driver.o
   2.434 +xen/drivers/char/console.o
   2.435 +xen/drivers/char/driver.o
   2.436 +xen/drivers/char/keyboard.o
   2.437 +xen/drivers/char/serial.o
   2.438 +xen/drivers/char/xen_kbd.o
   2.439 +xen/drivers/char/xen_serial.o
   2.440 +xen/drivers/ide/driver.o
   2.441 +xen/drivers/ide/ide-cd.o
   2.442 +xen/drivers/ide/ide-disk.o
   2.443 +xen/drivers/ide/ide-dma.o
   2.444 +xen/drivers/ide/ide-features.o
   2.445 +xen/drivers/ide/ide-geometry.o
   2.446 +xen/drivers/ide/ide-pci.o
   2.447 +xen/drivers/ide/ide-probe.o
   2.448 +xen/drivers/ide/ide-taskfile.o
   2.449 +xen/drivers/ide/ide-xeno.o
   2.450 +xen/drivers/ide/ide.o
   2.451 +xen/drivers/ide/piix.o
   2.452 +xen/drivers/message/fusion/driver.o
   2.453 +xen/drivers/message/fusion/mptbase.o
   2.454 +xen/drivers/message/fusion/mptscsih.o
   2.455 +xen/drivers/net/3c59x.o
   2.456 +xen/drivers/net/8139too.o
   2.457 +xen/drivers/net/Space.o
   2.458 +xen/drivers/net/driver.o
   2.459 +xen/drivers/net/dummy.o
   2.460 +xen/drivers/net/e100/e100.o
   2.461 +xen/drivers/net/e100/e100_config.o
   2.462 +xen/drivers/net/e100/e100_eeprom.o
   2.463 +xen/drivers/net/e100/e100_main.o
   2.464 +xen/drivers/net/e100/e100_phy.o
   2.465 +xen/drivers/net/e100/e100_test.o
   2.466 +xen/drivers/net/e1000/e1000.o
   2.467 +xen/drivers/net/e1000/e1000_ethtool.o
   2.468 +xen/drivers/net/e1000/e1000_hw.o
   2.469 +xen/drivers/net/e1000/e1000_main.o
   2.470 +xen/drivers/net/e1000/e1000_param.o
   2.471 +xen/drivers/net/e1000/kcompat.o
   2.472 +xen/drivers/net/ne/8390.o
   2.473 +xen/drivers/net/ne/ne.o
   2.474 +xen/drivers/net/ne/ne_drv.o
   2.475 +xen/drivers/net/net_init.o
   2.476 +xen/drivers/net/pcnet32.o
   2.477 +xen/drivers/net/setup.o
   2.478 +xen/drivers/net/tg3.o
   2.479 +xen/drivers/net/tulip/21142.o
   2.480 +xen/drivers/net/tulip/eeprom.o
   2.481 +xen/drivers/net/tulip/interrupt.o
   2.482 +xen/drivers/net/tulip/media.o
   2.483 +xen/drivers/net/tulip/pnic.o
   2.484 +xen/drivers/net/tulip/pnic2.o
   2.485 +xen/drivers/net/tulip/timer.o
   2.486 +xen/drivers/net/tulip/tulip.o
   2.487 +xen/drivers/net/tulip/tulip_core.o
   2.488 +xen/drivers/net/via-rhine.o
   2.489 +xen/drivers/pci/classlist.h
   2.490 +xen/drivers/pci/compat.o
   2.491 +xen/drivers/pci/devlist.h
   2.492 +xen/drivers/pci/driver.o
   2.493 +xen/drivers/pci/gen-devlist
   2.494 +xen/drivers/pci/names.o
   2.495 +xen/drivers/pci/pci.o
   2.496 +xen/drivers/pci/quirks.o
   2.497 +xen/drivers/pci/setup-res.o
   2.498 +xen/drivers/scsi/BusLogic.o
   2.499 +xen/drivers/scsi/aacraid/aachba.o
   2.500 +xen/drivers/scsi/aacraid/aacraid.o
   2.501 +xen/drivers/scsi/aacraid/commctrl.o
   2.502 +xen/drivers/scsi/aacraid/comminit.o
   2.503 +xen/drivers/scsi/aacraid/commsup.o
   2.504 +xen/drivers/scsi/aacraid/dpcsup.o
   2.505 +xen/drivers/scsi/aacraid/linit.o
   2.506 +xen/drivers/scsi/aacraid/rx.o
   2.507 +xen/drivers/scsi/aacraid/sa.o
   2.508 +xen/drivers/scsi/aic7xxx/aic7770.o
   2.509 +xen/drivers/scsi/aic7xxx/aic7770_osm.o
   2.510 +xen/drivers/scsi/aic7xxx/aic79xx_core.o
   2.511 +xen/drivers/scsi/aic7xxx/aic79xx_osm.o
   2.512 +xen/drivers/scsi/aic7xxx/aic79xx_osm_pci.o
   2.513 +xen/drivers/scsi/aic7xxx/aic79xx_pci.o
   2.514 +xen/drivers/scsi/aic7xxx/aic79xx_proc.o
   2.515 +xen/drivers/scsi/aic7xxx/aic7xxx.o
   2.516 +xen/drivers/scsi/aic7xxx/aic7xxx_93cx6.o
   2.517 +xen/drivers/scsi/aic7xxx/aic7xxx_core.o
   2.518 +xen/drivers/scsi/aic7xxx/aic7xxx_osm.o
   2.519 +xen/drivers/scsi/aic7xxx/aic7xxx_osm_pci.o
   2.520 +xen/drivers/scsi/aic7xxx/aic7xxx_pci.o
   2.521 +xen/drivers/scsi/aic7xxx/aic7xxx_proc.o
   2.522 +xen/drivers/scsi/constants.o
   2.523 +xen/drivers/scsi/driver.o
   2.524 +xen/drivers/scsi/hosts.o
   2.525 +xen/drivers/scsi/megaraid.o
   2.526 +xen/drivers/scsi/scsi.o
   2.527 +xen/drivers/scsi/scsi_dma.o
   2.528 +xen/drivers/scsi/scsi_error.o
   2.529 +xen/drivers/scsi/scsi_ioctl.o
   2.530 +xen/drivers/scsi/scsi_lib.o
   2.531 +xen/drivers/scsi/scsi_merge.o
   2.532 +xen/drivers/scsi/scsi_obsolete.o
   2.533 +xen/drivers/scsi/scsi_proc.o
   2.534 +xen/drivers/scsi/scsi_queue.o
   2.535 +xen/drivers/scsi/scsi_scan.o
   2.536 +xen/drivers/scsi/scsi_syms.o
   2.537 +xen/drivers/scsi/scsicam.o
   2.538 +xen/drivers/scsi/sd.o
   2.539 +xen/drivers/scsi/sym53c8xx_2/sym53c8xx.o
   2.540 +xen/drivers/scsi/sym53c8xx_2/sym_fw.o
   2.541 +xen/drivers/scsi/sym53c8xx_2/sym_glue.o
   2.542 +xen/drivers/scsi/sym53c8xx_2/sym_hipd.o
   2.543 +xen/drivers/scsi/sym53c8xx_2/sym_malloc.o
   2.544 +xen/drivers/scsi/sym53c8xx_2/sym_misc.o
   2.545 +xen/drivers/scsi/sym53c8xx_2/sym_nvram.o
   2.546 +xen/image
   2.547 +xen/image.dis
   2.548 +xen/image.gz
   2.549 +xen/image.s
   2.550 +xen/include/asm
   2.551 +xen/include/hypervisor-ifs/arch
   2.552 +xen/include/hypervisor-ifs/hypervisor-ifs
   2.553 +xen/include/hypervisor-ifs/segment.h~
   2.554 +xen/include/linux
   2.555 +xen/include/xen/compile.h
   2.556 +xen/include/xeno/compile.h
   2.557 +xen/include/xeno/physdisk.h~
   2.558 +xen/net/dev.o
   2.559 +xen/net/dev_mcast.o
   2.560 +xen/net/devinit.o
   2.561 +xen/net/eth.o
   2.562 +xen/net/network.o
   2.563 +xen/net/skbuff.o
   2.564 +xen/tools/elf-reloc
   2.565 +xen/tools/figlet/figlet
   2.566  xen/xen
   2.567  xen/xen.gz
   2.568  xen/xen.s
   2.569 -xen/drivers/pci/classlist.h
   2.570 -xen/drivers/pci/devlist.h
   2.571 -xen/drivers/pci/gen-devlist
   2.572 -xen/include/asm
   2.573 -xen/include/hypervisor-ifs/arch
   2.574 -xen/include/xen/compile.h
   2.575 -xen/tools/elf-reloc
   2.576 -xen/tools/figlet/figlet
   2.577 -TAGS
   2.578 +xenolinux-2.4.16-sparse/arch/xeno/drivers/block/Makefile.orig
   2.579 +xenolinux-2.4.16-sparse/arch/xeno/drivers/block/block.c.orig
   2.580 +xenolinux-2.4.16-sparse/scripts/kconfig.tk
   2.581 +xenolinux-2.4.21-sparse/arch/xeno/drivers/block/xl_block.c~
   2.582 +xenolinux-2.4.21-sparse/arch/xeno/drivers/block/xl_physdisk_proc.c.bak
   2.583 +xenolinux-2.4.21-sparse/arch/xeno/drivers/block/xl_physdisk_proc.c~
   2.584 +xenolinux-2.4.21-sparse/include/linux/blk.h~
   2.585 +xenolinux-2.4.22-sparse/arch/xeno/drivers/block/device
     3.1 --- a/tools/misc/xen-clone	Wed Mar 24 19:05:53 2004 +0000
     3.2 +++ b/tools/misc/xen-clone	Thu Mar 25 15:02:26 2004 +0000
     3.3 @@ -86,11 +86,15 @@ cd ../..
     3.4  mv linux-${LINUX_VER} xenolinux-${LINUX_VER}
     3.5  cd xenolinux-${LINUX_VER}
     3.6  
     3.7 -ARCH=xen make oldconfig
     3.8 -ARCH=xen make dep
     3.9 -ARCH=xen make bzImage
    3.10 -ARCH=xen make dist || ARCH=xen make install
    3.11 -ARCH=xen make modules
    3.12 -ARCH=xen make INSTALL_MOD_PATH=${TOP}/install modules_install
    3.13 +# cope with the change from ARCH=xeno to ARCH=xen
    3.14 +cd arch; XEN=`/bin/ls -d xen*`; cd ..
    3.15 +
    3.16 +# built it all
    3.17 +ARCH=$XEN make oldconfig
    3.18 +ARCH=$XEN make dep
    3.19 +ARCH=$XEN make bzImage
    3.20 +ARCH=$XEN make dist || ARCH=xen make install
    3.21 +ARCH=$XEN make modules
    3.22 +ARCH=$XEN make INSTALL_MOD_PATH=${TOP}/install modules_install
    3.23  cd ..
    3.24  
     4.1 --- a/tools/xc/lib/xc.h	Wed Mar 24 19:05:53 2004 +0000
     4.2 +++ b/tools/xc/lib/xc.h	Thu Mar 25 15:02:26 2004 +0000
     4.3 @@ -165,25 +165,38 @@ int xc_vbd_probe(int xc_handle,
     4.4                   xc_vbd_t *vbds);
     4.5  
     4.6  #define DOMID_SELF              (~1ULL)
     4.7 -#define EVTCHNSTAT_closed       0  /* Chennel is not in use.              */
     4.8 -#define EVTCHNSTAT_disconnected 1  /* Channel is not connected to remote. */
     4.9 -#define EVTCHNSTAT_connected    2  /* Channel is connected to remote.     */
    4.10 -int xc_evtchn_open(int xc_handle,
    4.11 -                   u64 dom1,   /* may be DOMID_SELF */
    4.12 -                   u64 dom2,   /* may be DOMID_SELF */
    4.13 -                   int *port1,
    4.14 -                   int *port2);
    4.15 +
    4.16 +typedef struct {
    4.17 +#define EVTCHNSTAT_closed       0  /* Chennel is not in use.                 */
    4.18 +#define EVTCHNSTAT_unbound      1  /* Channel is not bound to a source.      */
    4.19 +#define EVTCHNSTAT_interdomain  2  /* Channel is connected to remote domain. */
    4.20 +#define EVTCHNSTAT_pirq         3  /* Channel is bound to a phys IRQ line.   */
    4.21 +#define EVTCHNSTAT_virq         4  /* Channel is bound to a virtual IRQ line */
    4.22 +    int status;
    4.23 +    union {
    4.24 +        struct {
    4.25 +            u64 dom;
    4.26 +            int port;
    4.27 +        } interdomain;
    4.28 +        int pirq;
    4.29 +        int virq;
    4.30 +    } u;
    4.31 +} xc_evtchn_status_t;
    4.32 +
    4.33 +int xc_evtchn_bind_interdomain(int xc_handle,
    4.34 +                               u64 dom1,   /* may be DOMID_SELF */
    4.35 +                               u64 dom2,   /* may be DOMID_SELF */
    4.36 +                               int *port1,
    4.37 +                               int *port2);
    4.38  int xc_evtchn_close(int xc_handle,
    4.39                      u64 dom,   /* may be DOMID_SELF */
    4.40                      int port);
    4.41  int xc_evtchn_send(int xc_handle,
    4.42                     int local_port);
    4.43  int xc_evtchn_status(int xc_handle,
    4.44 -                     u64 dom1, /* may be DOMID_SELF */
    4.45 -                     int port1,
    4.46 -                     u64 *dom2,
    4.47 -                     int *port2,
    4.48 -                     int *chn_status);
    4.49 +                     u64 dom, /* may be DOMID_SELF */
    4.50 +                     int port,
    4.51 +                     xc_evtchn_status_t *status);
    4.52  
    4.53  int xc_physdev_pci_access_modify(int xc_handle,
    4.54                                   u64 domid,
     5.1 --- a/tools/xc/lib/xc_evtchn.c	Wed Mar 24 19:05:53 2004 +0000
     5.2 +++ b/tools/xc/lib/xc_evtchn.c	Thu Mar 25 15:02:26 2004 +0000
     5.3 @@ -29,25 +29,25 @@ static int do_evtchn_op(int xc_handle, e
     5.4   out1: return ret;
     5.5  }
     5.6  
     5.7 -int xc_evtchn_open(int xc_handle,
     5.8 -                   u64 dom1,
     5.9 -                   u64 dom2,
    5.10 -                   int *port1,
    5.11 -                   int *port2)
    5.12 +int xc_evtchn_bind_interdomain(int xc_handle,
    5.13 +                               u64 dom1,
    5.14 +                               u64 dom2,
    5.15 +                               int *port1,
    5.16 +                               int *port2)
    5.17  {
    5.18      evtchn_op_t op;
    5.19      int         rc;
    5.20  
    5.21 -    op.cmd = EVTCHNOP_open;
    5.22 -    op.u.open.dom1 = (domid_t)dom1;
    5.23 -    op.u.open.dom2 = (domid_t)dom2;
    5.24 +    op.cmd = EVTCHNOP_bind_interdomain;
    5.25 +    op.u.bind_interdomain.dom1 = (domid_t)dom1;
    5.26 +    op.u.bind_interdomain.dom2 = (domid_t)dom2;
    5.27     
    5.28      if ( (rc = do_evtchn_op(xc_handle, &op)) == 0 )
    5.29      {
    5.30          if ( port1 != NULL )
    5.31 -            *port1 = op.u.open.port1;
    5.32 +            *port1 = op.u.bind_interdomain.port1;
    5.33          if ( port2 != NULL )
    5.34 -            *port2 = op.u.open.port2;
    5.35 +            *port2 = op.u.bind_interdomain.port2;
    5.36      }
    5.37      
    5.38      return rc;
    5.39 @@ -77,27 +77,32 @@ int xc_evtchn_send(int xc_handle,
    5.40  
    5.41  
    5.42  int xc_evtchn_status(int xc_handle,
    5.43 -                     u64 dom1,
    5.44 -                     int port1,
    5.45 -                     u64 *dom2,
    5.46 -                     int *port2,
    5.47 -                     int *chn_status)
    5.48 +                     u64 dom,
    5.49 +                     int port,
    5.50 +                     xc_evtchn_status_t *status)
    5.51  {
    5.52      evtchn_op_t op;
    5.53      int         rc;
    5.54  
    5.55      op.cmd = EVTCHNOP_status;
    5.56 -    op.u.status.dom1  = (domid_t)dom1;
    5.57 -    op.u.status.port1 = port1;
    5.58 +    op.u.status.dom  = (domid_t)dom;
    5.59 +    op.u.status.port = port;
    5.60     
    5.61      if ( (rc = do_evtchn_op(xc_handle, &op)) == 0 )
    5.62      {
    5.63 -        if ( dom2 != NULL )
    5.64 -            *dom2 = (u64)op.u.status.dom2;
    5.65 -        if ( port2 != NULL )
    5.66 -            *port2 = op.u.status.port2;
    5.67 -        if ( chn_status != NULL )
    5.68 -            *chn_status = op.u.status.status;
    5.69 +        switch ( status->status = op.u.status.status )
    5.70 +        {
    5.71 +        case EVTCHNSTAT_interdomain:
    5.72 +            status->u.interdomain.dom  = (u64)op.u.status.u.interdomain.dom;
    5.73 +            status->u.interdomain.port = op.u.status.u.interdomain.port;
    5.74 +            break;
    5.75 +        case EVTCHNSTAT_pirq:
    5.76 +            status->u.pirq = op.u.status.u.pirq;
    5.77 +            break;
    5.78 +        case EVTCHNSTAT_virq:
    5.79 +            status->u.virq = op.u.status.u.virq;
    5.80 +            break;
    5.81 +        }
    5.82      }
    5.83      
    5.84      return rc;
     6.1 --- a/tools/xc/lib/xc_linux_build.c	Wed Mar 24 19:05:53 2004 +0000
     6.2 +++ b/tools/xc/lib/xc_linux_build.c	Thu Mar 25 15:02:26 2004 +0000
     6.3 @@ -248,6 +248,7 @@ static int setup_guestos(int xc_handle,
     6.4      /* shared_info page starts its life empty. */
     6.5      shared_info = map_pfn_writeable(pm_handle, shared_info_frame);
     6.6      memset(shared_info, 0, PAGE_SIZE);
     6.7 +    shared_info->evtchn_upcall_mask = ~0UL; /* mask all upcalls */
     6.8      unmap_pfn(pm_handle, shared_info);
     6.9  
    6.10      /* Send the page update requests down to the hypervisor. */
     7.1 --- a/tools/xc/lib/xc_netbsd_build.c	Wed Mar 24 19:05:53 2004 +0000
     7.2 +++ b/tools/xc/lib/xc_netbsd_build.c	Thu Mar 25 15:02:26 2004 +0000
     7.3 @@ -183,6 +183,7 @@ static int setup_guestos(int xc_handle,
     7.4      /* shared_info page starts its life empty. */
     7.5      shared_info = map_pfn_writeable(pm_handle, shared_info_frame);
     7.6      memset(shared_info, 0, PAGE_SIZE);
     7.7 +    shared_info->evtchn_upcall_mask = ~0UL; /* mask all upcalls */
     7.8      unmap_pfn(pm_handle, shared_info);
     7.9  
    7.10      /* Send the page update requests down to the hypervisor. */
     8.1 --- a/tools/xc/py/Xc.c	Wed Mar 24 19:05:53 2004 +0000
     8.2 +++ b/tools/xc/py/Xc.c	Thu Mar 25 15:02:26 2004 +0000
     8.3 @@ -687,9 +687,9 @@ static PyObject *pyxc_vbd_probe(PyObject
     8.4      return list;
     8.5  }
     8.6  
     8.7 -static PyObject *pyxc_evtchn_open(PyObject *self,
     8.8 -                                  PyObject *args,
     8.9 -                                  PyObject *kwds)
    8.10 +static PyObject *pyxc_evtchn_bind_interdomain(PyObject *self,
    8.11 +                                              PyObject *args,
    8.12 +                                              PyObject *kwds)
    8.13  {
    8.14      XcObject *xc = (XcObject *)self;
    8.15  
    8.16 @@ -702,7 +702,8 @@ static PyObject *pyxc_evtchn_open(PyObje
    8.17                                        &dom1, &dom2) )
    8.18          return NULL;
    8.19  
    8.20 -    if ( xc_evtchn_open(xc->xc_handle, dom1, dom2, &port1, &port2) != 0 )
    8.21 +    if ( xc_evtchn_bind_interdomain(xc->xc_handle, dom1, 
    8.22 +                                    dom2, &port1, &port2) != 0 )
    8.23          return PyErr_SetFromErrno(xc_error);
    8.24  
    8.25      return Py_BuildValue("{s:i,s:i}", 
    8.26 @@ -759,34 +760,45 @@ static PyObject *pyxc_evtchn_status(PyOb
    8.27      XcObject *xc = (XcObject *)self;
    8.28      PyObject *dict;
    8.29  
    8.30 -    u64 dom1 = DOMID_SELF, dom2;
    8.31 -    int port1, port2, status, ret;
    8.32 +    u64 dom = DOMID_SELF;
    8.33 +    int port, ret;
    8.34 +    xc_evtchn_status_t status;
    8.35  
    8.36      static char *kwd_list[] = { "port", "dom", NULL };
    8.37  
    8.38      if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|L", kwd_list, 
    8.39 -                                      &port1, &dom1) )
    8.40 +                                      &port, &dom) )
    8.41          return NULL;
    8.42  
    8.43 -    ret = xc_evtchn_status(xc->xc_handle, dom1, port1, &dom2, &port2, &status);
    8.44 +    ret = xc_evtchn_status(xc->xc_handle, dom, port, &status);
    8.45      if ( ret != 0 )
    8.46          return PyErr_SetFromErrno(xc_error);
    8.47  
    8.48 -    switch ( status )
    8.49 +    switch ( status.status )
    8.50      {
    8.51      case EVTCHNSTAT_closed:
    8.52          dict = Py_BuildValue("{s:s}", 
    8.53                               "status", "closed");
    8.54          break;
    8.55 -    case EVTCHNSTAT_disconnected:
    8.56 +    case EVTCHNSTAT_unbound:
    8.57          dict = Py_BuildValue("{s:s}", 
    8.58 -                             "status", "disconnected");
    8.59 +                             "status", "unbound");
    8.60 +        break;
    8.61 +    case EVTCHNSTAT_interdomain:
    8.62 +        dict = Py_BuildValue("{s:s,s:L,s:i}", 
    8.63 +                             "status", "interdomain",
    8.64 +                             "dom", status.u.interdomain.dom,
    8.65 +                             "port", status.u.interdomain.port);
    8.66          break;
    8.67 -    case EVTCHNSTAT_connected:
    8.68 -        dict = Py_BuildValue("{s:s,s:L,s:i}", 
    8.69 -                             "status", "connected",
    8.70 -                             "dom", dom2,
    8.71 -                             "port", port2);
    8.72 +    case EVTCHNSTAT_pirq:
    8.73 +        dict = Py_BuildValue("{s:s,s:i}", 
    8.74 +                             "status", "pirq",
    8.75 +                             "irq", status.u.pirq);
    8.76 +        break;
    8.77 +    case EVTCHNSTAT_virq:
    8.78 +        dict = Py_BuildValue("{s:s,s:i}", 
    8.79 +                             "status", "virq",
    8.80 +                             "irq", status.u.virq);
    8.81          break;
    8.82      default:
    8.83          dict = Py_BuildValue("{}");
    8.84 @@ -1134,8 +1146,8 @@ static PyMethodDef pyxc_methods[] = {
    8.85        " writeable  [int]:  Bool - is this VBD writeable?\n"
    8.86        " nr_sectors [long]: Size of this VBD, in 512-byte sectors.\n" },
    8.87  
    8.88 -    { "evtchn_open", 
    8.89 -      (PyCFunction)pyxc_evtchn_open, 
    8.90 +    { "evtchn_bind_interdomain", 
    8.91 +      (PyCFunction)pyxc_evtchn_bind_interdomain, 
    8.92        METH_VARARGS | METH_KEYWORDS, "\n"
    8.93        "Open an event channel between two domains.\n"
    8.94        " dom1 [long, SELF]: First domain to be connected.\n"
    8.95 @@ -1166,10 +1178,13 @@ static PyMethodDef pyxc_methods[] = {
    8.96        " dom  [long, SELF]: Dom-id of one endpoint of the channel.\n"
    8.97        " port [int]:        Port-id of one endpoint of the channel.\n\n"
    8.98        "Returns: [dict] dictionary is empty on failure.\n"
    8.99 -      " status [str]:  'closed', 'disconnected', or 'connected'.\n"
   8.100 -      "The following are also returned if 'status' is 'connected':\n"
   8.101 -      " dom  [long]: Port-id for endpoint at dom1.\n"
   8.102 -      " port [int]:  Port-id for endpoint at dom2.\n" },
   8.103 +      " status [str]:  'closed', 'unbound', 'interdomain', 'pirq',"
   8.104 +      " or 'virq'.\n"
   8.105 +      "The following are returned if 'status' is 'interdomain':\n"
   8.106 +      " dom  [long]: Dom-id of remote endpoint.\n"
   8.107 +      " port [int]:  Port-id of remote endpoint.\n"
   8.108 +      "The following are returned if 'status' is 'pirq' or 'virq':\n"
   8.109 +      " irq  [int]:  IRQ number.\n" },
   8.110  
   8.111      { "physdev_pci_access_modify",
   8.112        (PyCFunction)pyxc_physdev_pci_access_modify,
     9.1 --- a/tools/xend/lib/main.py	Wed Mar 24 19:05:53 2004 +0000
     9.2 +++ b/tools/xend/lib/main.py	Thu Mar 25 15:02:26 2004 +0000
     9.3 @@ -175,16 +175,16 @@ def daemon_loop():
     9.4              # getting clogged with stale connections.
     9.5              if type == notifier.DISCONNECT:
     9.6                  ret = xc.evtchn_status(idx)
     9.7 -                if ret['status'] != 'connected':
     9.8 +                if ret['status'] == 'interdomain':
     9.9                      notifier.clear(idx, notifier.NORMAL)
    9.10                      notifier.clear(idx, notifier.DISCONNECT)
    9.11                      if control_list.has_key(idx):
    9.12                          (port, rbuf, wbuf, con_if) =  control_list[idx]
    9.13                          con_if.close()
    9.14                          del control_list[idx], port, rbuf, wbuf, con_if
    9.15 -                    elif ret['status'] == 'disconnected':
    9.16 -                        # There's noone to do the closure for us...
    9.17 -                        xc.evtchn_close(idx)
    9.18 +                elif ret['status'] == 'unbound':
    9.19 +                    # There's noone to do the closure for us...
    9.20 +                    xc.evtchn_close(idx)
    9.21  
    9.22              # A standard notification: probably means there are messages to
    9.23              # read or that there is space to write messages.
    10.1 --- a/tools/xend/lib/utils.c	Wed Mar 24 19:05:53 2004 +0000
    10.2 +++ b/tools/xend/lib/utils.c	Thu Mar 25 15:02:26 2004 +0000
    10.3 @@ -632,7 +632,8 @@ static PyObject *xu_port_new(PyObject *s
    10.4          goto fail2;
    10.5      }
    10.6  
    10.7 -    if ( xc_evtchn_open(xup->xc_handle, DOMID_SELF, dom, &port1, &port2) != 0 )
    10.8 +    if ( xc_evtchn_bind_interdomain(xup->xc_handle, 
    10.9 +                                    DOMID_SELF, dom, &port1, &port2) != 0 )
   10.10      {
   10.11          PyErr_SetString(port_error, "Could not open channel to domain");
   10.12          goto fail3;
    11.1 --- a/xen/arch/i386/Rules.mk	Wed Mar 24 19:05:53 2004 +0000
    11.2 +++ b/xen/arch/i386/Rules.mk	Thu Mar 25 15:02:26 2004 +0000
    11.3 @@ -8,7 +8,7 @@ MONITOR_BASE := 0xFC500000
    11.4  # Bootloader should load monitor to this real address
    11.5  LOAD_BASE    := 0x00100000
    11.6  CFLAGS  := -nostdinc -fno-builtin -fno-common -fno-strict-aliasing 
    11.7 -CFLAGS  += -iwithprefix include -O3 -Wall -DMONITOR_BASE=$(MONITOR_BASE)
    11.8 +CFLAGS  += -iwithprefix include -O3 -Wall -Werror -DMONITOR_BASE=$(MONITOR_BASE)
    11.9  CFLAGS  += -fomit-frame-pointer -I$(BASEDIR)/include -D__KERNEL__ -DNDEBUG
   11.10  #CFLAGS  += -fomit-frame-pointer -I$(BASEDIR)/include -D__KERNEL__
   11.11  CFLAGS  += -Wno-pointer-arith -Wredundant-decls -m32
    12.1 --- a/xen/arch/i386/domain_page.c	Wed Mar 24 19:05:53 2004 +0000
    12.2 +++ b/xen/arch/i386/domain_page.c	Thu Mar 25 15:02:26 2004 +0000
    12.3 @@ -45,6 +45,8 @@ void *map_domain_mem(unsigned long pa)
    12.4      unsigned long *cache = mapcache;
    12.5      unsigned long flags;
    12.6  
    12.7 +    perfc_incrc(map_domain_mem_count);
    12.8 +
    12.9      spin_lock_irqsave(&map_lock, flags);
   12.10  
   12.11      /* Has some other CPU caused a wrap? We must flush if so. */
    13.1 --- a/xen/arch/i386/entry.S	Wed Mar 24 19:05:53 2004 +0000
    13.2 +++ b/xen/arch/i386/entry.S	Thu Mar 25 15:02:26 2004 +0000
    13.3 @@ -112,8 +112,8 @@ FAILSAFE_SEL    = 32
    13.4  FAILSAFE_ADDR   = 36
    13.5  
    13.6  /* Offsets in shared_info_t */
    13.7 -EVENTS          =  0
    13.8 -EVENTS_MASK     =  4
    13.9 +UPCALL_PENDING  = 0
   13.10 +UPCALL_MASK     = 4
   13.11  
   13.12  /* Offsets in guest_trap_bounce */
   13.13  GTB_ERROR_CODE   =  0
   13.14 @@ -368,15 +368,12 @@ test_all_events:
   13.15          jnz  process_hyp_events
   13.16  /*test_guest_events:*/
   13.17          movl SHARED_INFO(%ebx),%eax
   13.18 -        shl  $31,%ecx                   # %ecx = EVENTS_MASTER_ENABLE_MASK
   13.19 -        test %ecx,EVENTS_MASK(%eax)     
   13.20 -        jz   restore_all_guest          # only notify if master switch enabled
   13.21 -        movl EVENTS(%eax),%ecx
   13.22 -        andl EVENTS_MASK(%eax),%ecx
   13.23 -        jz   restore_all_guest          # skip if no events to deliver
   13.24 +        movl UPCALL_MASK(%eax),%ecx
   13.25          notl %ecx
   13.26 -        btrl $31,%ecx                   # NB. We clear all events that are
   13.27 -        andl %ecx,EVENTS_MASK(%eax)     # being delivered + master enable.
   13.28 +        andl UPCALL_PENDING(%eax),%ecx  # ECX = pending & ~mask
   13.29 +        andl $1,%ecx                    # Is bit 0 pending and not masked?
   13.30 +        jz   restore_all_guest
   13.31 +        orl  %ecx,UPCALL_MASK(%eax)     # Upcalls are masked during delivery
   13.32  /*process_guest_events:*/
   13.33          movzwl PROCESSOR(%ebx),%edx
   13.34          shl  $4,%edx                    # sizeof(guest_trap_bounce) == 16
    14.1 --- a/xen/arch/i386/process.c	Wed Mar 24 19:05:53 2004 +0000
    14.2 +++ b/xen/arch/i386/process.c	Thu Mar 25 15:02:26 2004 +0000
    14.3 @@ -29,9 +29,9 @@
    14.4  #include <asm/i387.h>
    14.5  #include <asm/mpspec.h>
    14.6  #include <asm/ldt.h>
    14.7 -
    14.8  #include <xen/irq.h>
    14.9  #include <xen/event.h>
   14.10 +#include <xen/shadow.h>
   14.11  
   14.12  int hlt_counter;
   14.13  
   14.14 @@ -281,7 +281,13 @@ void switch_to(struct task_struct *prev_
   14.15      }
   14.16  
   14.17      /* Switch page tables.  */
   14.18 -    write_cr3_counted(pagetable_val(next_p->mm.pagetable));
   14.19 +    if( next_p->mm.shadow_mode )
   14.20 +      {
   14.21 +	check_pagetable( next_p, next_p->mm.pagetable, "switch" );
   14.22 +	write_cr3_counted(pagetable_val(next_p->mm.shadow_table));
   14.23 +      }
   14.24 +    else
   14.25 +      write_cr3_counted(pagetable_val(next_p->mm.pagetable));
   14.26  
   14.27      set_current(next_p);
   14.28  
    15.1 --- a/xen/arch/i386/traps.c	Wed Mar 24 19:05:53 2004 +0000
    15.2 +++ b/xen/arch/i386/traps.c	Thu Mar 25 15:02:26 2004 +0000
    15.3 @@ -39,6 +39,7 @@
    15.4  #include <xen/spinlock.h>
    15.5  #include <xen/irq.h>
    15.6  #include <xen/perfc.h>
    15.7 +#include <xen/shadow.h>
    15.8  #include <asm/domain_page.h>
    15.9  #include <asm/system.h>
   15.10  #include <asm/io.h>
   15.11 @@ -205,7 +206,7 @@ static inline void do_trap(int trapnr, c
   15.12      gtb->cs         = ti->cs;
   15.13      gtb->eip        = ti->address;
   15.14      if ( TI_GET_IF(ti) )
   15.15 -        clear_bit(EVENTS_MASTER_ENABLE_BIT, &p->shared_info->events_mask);
   15.16 +        set_bit(0, &p->shared_info->evtchn_upcall_mask);
   15.17      return; 
   15.18  
   15.19   fault_in_hypervisor:
   15.20 @@ -276,7 +277,7 @@ asmlinkage void do_int3(struct pt_regs *
   15.21      gtb->cs         = ti->cs;
   15.22      gtb->eip        = ti->address;
   15.23      if ( TI_GET_IF(ti) )
   15.24 -        clear_bit(EVENTS_MASTER_ENABLE_BIT, &p->shared_info->events_mask);
   15.25 +        set_bit(0, &p->shared_info->evtchn_upcall_mask);
   15.26      return;
   15.27  
   15.28  }
   15.29 @@ -323,6 +324,8 @@ asmlinkage void do_page_fault(struct pt_
   15.30  
   15.31      __asm__ __volatile__ ("movl %%cr2,%0" : "=r" (addr) : );
   15.32  
   15.33 +    perfc_incrc(page_faults);
   15.34 +
   15.35      if ( unlikely(addr >= LDT_VIRT_START) && 
   15.36           (addr < (LDT_VIRT_START + (p->mm.ldt_ents*LDT_ENTRY_SIZE))) )
   15.37      {
   15.38 @@ -336,6 +339,12 @@ asmlinkage void do_page_fault(struct pt_
   15.39              return; /* successfully copied the mapping */
   15.40      }
   15.41  
   15.42 +    if ( unlikely( p->mm.shadow_mode ) && addr < PAGE_OFFSET &&
   15.43 +	 shadow_fault( addr, error_code ) )
   15.44 +      {
   15.45 +	return; // return true if fault was handled 
   15.46 +      }
   15.47 +
   15.48      if ( unlikely(!(regs->xcs & 3)) )
   15.49          goto fault_in_hypervisor;
   15.50  
   15.51 @@ -346,14 +355,15 @@ asmlinkage void do_page_fault(struct pt_
   15.52      gtb->cs         = ti->cs;
   15.53      gtb->eip        = ti->address;
   15.54      if ( TI_GET_IF(ti) )
   15.55 -        clear_bit(EVENTS_MASTER_ENABLE_BIT, &p->shared_info->events_mask);
   15.56 +        set_bit(0, &p->shared_info->evtchn_upcall_mask);
   15.57      return; 
   15.58  
   15.59   fault_in_hypervisor:
   15.60  
   15.61      if ( likely((fixup = search_exception_table(regs->eip)) != 0) )
   15.62      {
   15.63 -        DPRINTK("Page fault: %08lx -> %08lx\n", regs->eip, fixup);
   15.64 +        perfc_incrc(copy_user_faults);
   15.65 +        //DPRINTK("copy_user fault: %08lx -> %08lx\n", regs->eip, fixup);
   15.66          regs->eip = fixup;
   15.67          regs->xds = regs->xes = regs->xfs = regs->xgs = __HYPERVISOR_DS;
   15.68          return;
   15.69 @@ -434,7 +444,7 @@ asmlinkage void do_general_protection(st
   15.70      gtb->cs         = ti->cs;
   15.71      gtb->eip        = ti->address;
   15.72      if ( TI_GET_IF(ti) )
   15.73 -        clear_bit(EVENTS_MASTER_ENABLE_BIT, &p->shared_info->events_mask);
   15.74 +        set_bit(0, &p->shared_info->evtchn_upcall_mask);
   15.75      return;
   15.76  
   15.77   gp_in_kernel:
    16.1 --- a/xen/common/debug.c	Wed Mar 24 19:05:53 2004 +0000
    16.2 +++ b/xen/common/debug.c	Thu Mar 25 15:02:26 2004 +0000
    16.3 @@ -91,7 +91,11 @@ int pdb_change_values(domid_t domain, u_
    16.4  
    16.5      if ((addr >> PAGE_SHIFT) == ((addr + length - 1) >> PAGE_SHIFT))
    16.6      {
    16.7 -        l2_table = map_domain_mem(pagetable_val(p->mm.pagetable));
    16.8 +        if (p->mm.shadow_mode )
    16.9 +          l2_table = map_domain_mem(pagetable_val(p->mm.shadow_table));
   16.10 +	else
   16.11 +          l2_table = map_domain_mem(pagetable_val(p->mm.pagetable));
   16.12 +
   16.13  	l2_table += l2_table_offset(addr);
   16.14  	if (!(l2_pgentry_val(*l2_table) & _PAGE_PRESENT)) 
   16.15  	{
   16.16 @@ -224,16 +228,12 @@ void pdb_do_debug (dom0_op_t *op)
   16.17  
   16.18          case 's' :
   16.19  	{
   16.20 -	    unsigned long cpu_mask;
   16.21  	    struct task_struct * p = find_domain_by_id(op->u.debug.domain);
   16.22  
   16.23  	    if (p != NULL)
   16.24  	    {
   16.25  	        if (p->state != TASK_STOPPED)
   16.26 -		{
   16.27 -		    cpu_mask = mark_guest_event(p, _EVENT_STOP);
   16.28 -		    guest_event_notify(cpu_mask);
   16.29 -		}
   16.30 +                    send_guest_virq(p, VIRQ_STOP);
   16.31  		put_task_struct(p);
   16.32  	    }
   16.33  	    else
    17.1 --- a/xen/common/dom0_ops.c	Wed Mar 24 19:05:53 2004 +0000
    17.2 +++ b/xen/common/dom0_ops.c	Thu Mar 25 15:02:26 2004 +0000
    17.3 @@ -18,6 +18,7 @@
    17.4  #include <asm/pdb.h>
    17.5  #include <xen/trace.h>
    17.6  #include <xen/console.h>
    17.7 +#include <xen/shadow.h>
    17.8  #include <hypervisor-ifs/sched_ctl.h>
    17.9  
   17.10  extern unsigned int alloc_new_dom_mem(struct task_struct *, unsigned int);
   17.11 @@ -493,6 +494,19 @@ long do_dom0_op(dom0_op_t *u_dom0_op)
   17.12                                          op->u.pcidev_access.enable);
   17.13      }
   17.14      break;
   17.15 +
   17.16 +    case DOM0_SHADOW_CONTROL:
   17.17 +    {
   17.18 +        struct task_struct *p; 
   17.19 +	
   17.20 +	p = find_domain_by_id( op->u.shadow_control.domain );
   17.21 +	if ( p )
   17.22 +	{
   17.23 +            ret = shadow_mode_control(p, op->u.shadow_control.op );
   17.24 +	    put_task_struct(p);
   17.25 +        }
   17.26 +    }
   17.27 +    break;
   17.28       
   17.29      default:
   17.30          ret = -ENOSYS;
    18.1 --- a/xen/common/domain.c	Wed Mar 24 19:05:53 2004 +0000
    18.2 +++ b/xen/common/domain.c	Thu Mar 25 15:02:26 2004 +0000
    18.3 @@ -9,6 +9,7 @@
    18.4  #include <xen/delay.h>
    18.5  #include <xen/event.h>
    18.6  #include <xen/time.h>
    18.7 +#include <xen/shadow.h>
    18.8  #include <hypervisor-ifs/dom0_ops.h>
    18.9  #include <asm/io.h>
   18.10  #include <asm/domain_page.h>
   18.11 @@ -53,14 +54,19 @@ struct task_struct *do_createdomain(domi
   18.12  
   18.13      if ( p->domain != IDLE_DOMAIN_ID )
   18.14      {
   18.15 +        if ( init_event_channels(p) != 0 )
   18.16 +        {
   18.17 +            free_task_struct(p);
   18.18 +            return NULL;
   18.19 +        }
   18.20 +        
   18.21          /* We use a large intermediate to avoid overflow in sprintf. */
   18.22          sprintf(buf, "Domain-%llu", dom_id);
   18.23          strncpy(p->name, buf, MAX_DOMAIN_NAME);
   18.24          p->name[MAX_DOMAIN_NAME-1] = '\0';
   18.25  
   18.26          spin_lock_init(&p->blk_ring_lock);
   18.27 -        spin_lock_init(&p->event_channel_lock);
   18.28 -        
   18.29 +
   18.30          p->addr_limit = USER_DS;
   18.31          
   18.32          spin_lock_init(&p->page_list_lock);
   18.33 @@ -133,8 +139,6 @@ void kill_domain_with_errmsg(const char 
   18.34  
   18.35  void __kill_domain(struct task_struct *p)
   18.36  {
   18.37 -    extern void destroy_event_channels(struct task_struct *);
   18.38 -
   18.39      int i;
   18.40      struct task_struct **pp;
   18.41      unsigned long flags;
   18.42 @@ -197,25 +201,16 @@ void kill_domain(void)
   18.43  long kill_other_domain(domid_t dom, int force)
   18.44  {
   18.45      struct task_struct *p;
   18.46 -    unsigned long cpu_mask = 0;
   18.47  
   18.48 -    p = find_domain_by_id(dom);
   18.49 -    if ( p == NULL ) return -ESRCH;
   18.50 +    if ( (p = find_domain_by_id(dom)) == NULL )
   18.51 +        return -ESRCH;
   18.52  
   18.53      if ( p->state == TASK_STOPPED )
   18.54 -    {
   18.55          __kill_domain(p);
   18.56 -    }
   18.57      else if ( force )
   18.58 -    {
   18.59 -        cpu_mask = mark_hyp_event(p, _HYP_EVENT_DIE);
   18.60 -        hyp_event_notify(cpu_mask);
   18.61 -    }
   18.62 +        send_hyp_event(p, _HYP_EVENT_DIE);
   18.63      else
   18.64 -    {
   18.65 -        cpu_mask = mark_guest_event(p, _EVENT_DIE);
   18.66 -        guest_event_notify(cpu_mask);
   18.67 -    }
   18.68 +        send_guest_virq(p, VIRQ_DIE);
   18.69  
   18.70      put_task_struct(p);
   18.71      return 0;
   18.72 @@ -234,7 +229,6 @@ void stop_domain(void)
   18.73  
   18.74  long stop_other_domain(domid_t dom)
   18.75  {
   18.76 -    unsigned long cpu_mask;
   18.77      struct task_struct *p;
   18.78      
   18.79      if ( dom == 0 )
   18.80 @@ -244,10 +238,7 @@ long stop_other_domain(domid_t dom)
   18.81      if ( p == NULL) return -ESRCH;
   18.82      
   18.83      if ( p->state != TASK_STOPPED )
   18.84 -    {
   18.85 -        cpu_mask = mark_guest_event(p, _EVENT_STOP);
   18.86 -        guest_event_notify(cpu_mask);
   18.87 -    }
   18.88 +        send_guest_virq(p, VIRQ_STOP);
   18.89      
   18.90      put_task_struct(p);
   18.91      return 0;
   18.92 @@ -342,12 +333,14 @@ void free_domain_page(struct pfn_info *p
   18.93          if ( !(page->count_and_flags & PGC_zombie) )
   18.94          {
   18.95              page->tlbflush_timestamp = tlbflush_clock;
   18.96 -            page->u.cpu_mask = 1 << p->processor;
   18.97 -
   18.98 -            spin_lock(&p->page_list_lock);
   18.99 -            list_del(&page->list);
  18.100 -            p->tot_pages--;
  18.101 -            spin_unlock(&p->page_list_lock);
  18.102 +	    if (p)
  18.103 +	    {
  18.104 +                page->u.cpu_mask = 1 << p->processor;
  18.105 +                spin_lock(&p->page_list_lock);
  18.106 +		list_del(&page->list);
  18.107 +		p->tot_pages--;
  18.108 +		spin_unlock(&p->page_list_lock);
  18.109 +	    }
  18.110          }
  18.111  
  18.112          page->count_and_flags = 0;
  18.113 @@ -757,6 +750,7 @@ int setup_guestos(struct task_struct *p,
  18.114      /* Set up shared info area. */
  18.115      update_dom_time(p->shared_info);
  18.116      p->shared_info->domain_time = 0;
  18.117 +    p->shared_info->evtchn_upcall_mask = ~0UL; /* mask all upcalls */
  18.118  
  18.119      virt_startinfo_address = (start_info_t *)
  18.120          (virt_load_address + ((alloc_index - 1) << PAGE_SHIFT));
  18.121 @@ -855,6 +849,10 @@ int setup_guestos(struct task_struct *p,
  18.122  
  18.123      set_bit(PF_CONSTRUCTED, &p->flags);
  18.124  
  18.125 +#if 0 // XXXXX DO NOT CHECK IN ENBALED !!! (but useful for testing so leave) 
  18.126 +    shadow_mode_enable(p, SHM_test); 
  18.127 +#endif
  18.128 +
  18.129      new_thread(p, 
  18.130                 (unsigned long)virt_load_address, 
  18.131                 (unsigned long)virt_stack_address, 
    19.1 --- a/xen/common/event_channel.c	Wed Mar 24 19:05:53 2004 +0000
    19.2 +++ b/xen/common/event_channel.c	Thu Mar 25 15:02:26 2004 +0000
    19.3 @@ -25,7 +25,8 @@
    19.4  #include <hypervisor-ifs/hypervisor-if.h>
    19.5  #include <hypervisor-ifs/event_channel.h>
    19.6  
    19.7 -#define MAX_EVENT_CHANNELS 1024
    19.8 +#define INIT_EVENT_CHANNELS   16
    19.9 +#define MAX_EVENT_CHANNELS  1024
   19.10  
   19.11  static int get_free_port(struct task_struct *p)
   19.12  {
   19.13 @@ -65,28 +66,11 @@ static int get_free_port(struct task_str
   19.14      return port;
   19.15  }
   19.16  
   19.17 -static inline unsigned long set_event_pending(struct task_struct *p, int port)
   19.18 -{
   19.19 -    if ( !test_and_set_bit(port,    &p->shared_info->event_channel_pend[0]) &&
   19.20 -         !test_and_set_bit(port>>5, &p->shared_info->event_channel_pend_sel) )
   19.21 -        return mark_guest_event(p, _EVENT_EVTCHN);
   19.22 -    return 0;
   19.23 -}
   19.24 -
   19.25 -static inline unsigned long set_event_disc(struct task_struct *p, int port)
   19.26 -{
   19.27 -    if ( !test_and_set_bit(port,    &p->shared_info->event_channel_disc[0]) &&
   19.28 -         !test_and_set_bit(port>>5, &p->shared_info->event_channel_disc_sel) )
   19.29 -        return mark_guest_event(p, _EVENT_EVTCHN);
   19.30 -    return 0;
   19.31 -}
   19.32 -
   19.33 -static long event_channel_open(evtchn_open_t *open)
   19.34 +static long evtchn_bind_interdomain(evtchn_bind_interdomain_t *bind)
   19.35  {
   19.36      struct task_struct *p1, *p2;
   19.37      int                 port1 = 0, port2 = 0;
   19.38 -    unsigned long       cpu_mask;
   19.39 -    domid_t             dom1 = open->dom1, dom2 = open->dom2;
   19.40 +    domid_t             dom1 = bind->dom1, dom2 = bind->dom2;
   19.41      long                rc = 0;
   19.42  
   19.43      if ( !IS_PRIV(current) )
   19.44 @@ -130,21 +114,16 @@ static long event_channel_open(evtchn_op
   19.45          goto out;
   19.46      }
   19.47  
   19.48 -    p1->event_channel[port1].remote_dom  = p2;
   19.49 -    p1->event_channel[port1].remote_port = (u16)port2;
   19.50 -    p1->event_channel[port1].state       = ECS_CONNECTED;
   19.51 -
   19.52 -    p2->event_channel[port2].remote_dom  = p1;
   19.53 -    p2->event_channel[port2].remote_port = (u16)port1;
   19.54 -    p2->event_channel[port2].state       = ECS_CONNECTED;
   19.55 +    p1->event_channel[port1].u.remote.dom  = p2;
   19.56 +    p1->event_channel[port1].u.remote.port = (u16)port2;
   19.57 +    p1->event_channel[port1].state         = ECS_INTERDOMAIN;
   19.58  
   19.59 -    /* Ensure that the disconnect signal is not asserted. */
   19.60 -    clear_bit(port1, &p1->shared_info->event_channel_disc[0]);
   19.61 -    clear_bit(port2, &p2->shared_info->event_channel_disc[0]);
   19.62 +    p2->event_channel[port2].u.remote.dom  = p1;
   19.63 +    p2->event_channel[port2].u.remote.port = (u16)port1;
   19.64 +    p2->event_channel[port2].state         = ECS_INTERDOMAIN;
   19.65  
   19.66 -    cpu_mask  = set_event_pending(p1, port1);
   19.67 -    cpu_mask |= set_event_pending(p2, port2);
   19.68 -    guest_event_notify(cpu_mask);
   19.69 +    evtchn_set_pending(p1, port1);
   19.70 +    evtchn_set_pending(p2, port2);
   19.71      
   19.72   out:
   19.73      spin_unlock(&p1->event_channel_lock);
   19.74 @@ -154,19 +133,55 @@ static long event_channel_open(evtchn_op
   19.75      put_task_struct(p1);
   19.76      put_task_struct(p2);
   19.77  
   19.78 -    open->port1 = port1;
   19.79 -    open->port2 = port2;
   19.80 +    bind->port1 = port1;
   19.81 +    bind->port2 = port2;
   19.82  
   19.83      return rc;
   19.84  }
   19.85  
   19.86  
   19.87 -static long __event_channel_close(struct task_struct *p1, int port1)
   19.88 +static long evtchn_bind_virq(evtchn_bind_virq_t *bind)
   19.89 +{
   19.90 +    struct task_struct *p = current;
   19.91 +    int virq = bind->virq;
   19.92 +    int port;
   19.93 +
   19.94 +    if ( virq >= NR_VIRQS )
   19.95 +        return -EINVAL;
   19.96 +
   19.97 +    spin_lock(&p->event_channel_lock);
   19.98 +
   19.99 +    /*
  19.100 +     * Port 0 is the fallback port for VIRQs that haven't been explicitly
  19.101 +     * bound yet. The exception is the 'error VIRQ', which is permanently 
  19.102 +     * bound to port 0.
  19.103 +     */
  19.104 +    if ( ((port = p->virq_to_evtchn[virq]) != 0) ||
  19.105 +         (virq == VIRQ_ERROR) ||
  19.106 +         ((port = get_free_port(p)) < 0) )
  19.107 +        goto out;
  19.108 +
  19.109 +    p->event_channel[port].state  = ECS_VIRQ;
  19.110 +    p->event_channel[port].u.virq = virq;
  19.111 +
  19.112 +    p->virq_to_evtchn[virq] = port;
  19.113 +
  19.114 + out:
  19.115 +    spin_unlock(&p->event_channel_lock);
  19.116 +
  19.117 +    if ( port < 0 )
  19.118 +        return port;
  19.119 +
  19.120 +    bind->port = port;
  19.121 +    return 0;
  19.122 +}
  19.123 +
  19.124 +
  19.125 +static long __evtchn_close(struct task_struct *p1, int port1)
  19.126  {
  19.127      struct task_struct *p2 = NULL;
  19.128      event_channel_t    *chn1, *chn2;
  19.129      int                 port2;
  19.130 -    unsigned long       cpu_mask = 0;
  19.131      long                rc = 0;
  19.132  
  19.133   again:
  19.134 @@ -174,18 +189,34 @@ static long __event_channel_close(struct
  19.135  
  19.136      chn1 = p1->event_channel;
  19.137  
  19.138 -    if ( (port1 < 0) || (port1 >= p1->max_event_channel) || 
  19.139 -         (chn1[port1].state == ECS_FREE) )
  19.140 +    /* NB. Port 0 is special (VIRQ_ERROR). Never let it be closed. */
  19.141 +    if ( (port1 <= 0) || (port1 >= p1->max_event_channel) )
  19.142      {
  19.143          rc = -EINVAL;
  19.144          goto out;
  19.145      }
  19.146  
  19.147 -    if ( chn1[port1].state == ECS_CONNECTED )
  19.148 +    switch ( chn1[port1].state )
  19.149      {
  19.150 +    case ECS_FREE:
  19.151 +        rc = -EINVAL;
  19.152 +        goto out;
  19.153 +
  19.154 +    case ECS_UNBOUND:
  19.155 +        break;
  19.156 +
  19.157 +    case ECS_PIRQ:
  19.158 +        p1->pirq_to_evtchn[chn1[port1].u.pirq] = 0;
  19.159 +        break;
  19.160 +
  19.161 +    case ECS_VIRQ:
  19.162 +        p1->virq_to_evtchn[chn1[port1].u.virq] = 0;
  19.163 +        break;
  19.164 +
  19.165 +    case ECS_INTERDOMAIN:
  19.166          if ( p2 == NULL )
  19.167          {
  19.168 -            p2 = chn1[port1].remote_dom;
  19.169 +            p2 = chn1[port1].u.remote.dom;
  19.170              get_task_struct(p2);
  19.171  
  19.172              if ( p1->domain < p2->domain )
  19.173 @@ -199,35 +230,39 @@ static long __event_channel_close(struct
  19.174                  goto again;
  19.175              }
  19.176          }
  19.177 -        else if ( p2 != chn1[port1].remote_dom )
  19.178 +        else if ( p2 != chn1[port1].u.remote.dom )
  19.179          {
  19.180              rc = -EINVAL;
  19.181              goto out;
  19.182          }
  19.183          
  19.184          chn2  = p2->event_channel;
  19.185 -        port2 = chn1[port1].remote_port;
  19.186 +        port2 = chn1[port1].u.remote.port;
  19.187  
  19.188          if ( port2 >= p2->max_event_channel )
  19.189              BUG();
  19.190 -        if ( chn2[port2].state != ECS_CONNECTED )
  19.191 +        if ( chn2[port2].state != ECS_INTERDOMAIN )
  19.192              BUG();
  19.193 -        if ( chn2[port2].remote_dom != p1 )
  19.194 +        if ( chn2[port2].u.remote.dom != p1 )
  19.195              BUG();
  19.196  
  19.197 -        chn2[port2].state       = ECS_DISCONNECTED;
  19.198 -        chn2[port2].remote_dom  = NULL;
  19.199 -        chn2[port2].remote_port = 0xFFFF;
  19.200 +        chn2[port2].state         = ECS_UNBOUND;
  19.201 +        chn2[port2].u.remote.dom  = NULL;
  19.202 +        chn2[port2].u.remote.port = 0xFFFF;
  19.203  
  19.204 -        cpu_mask |= set_event_disc(p2, port2);
  19.205 +        evtchn_set_exception(p2, port2);
  19.206 +
  19.207 +        break;
  19.208 +
  19.209 +    default:
  19.210 +        BUG();
  19.211      }
  19.212  
  19.213 -    chn1[port1].state       = ECS_FREE;
  19.214 -    chn1[port1].remote_dom  = NULL;
  19.215 -    chn1[port1].remote_port = 0xFFFF;
  19.216 +    chn1[port1].state         = ECS_FREE;
  19.217 +    chn1[port1].u.remote.dom  = NULL;
  19.218 +    chn1[port1].u.remote.port = 0xFFFF;
  19.219      
  19.220 -    cpu_mask |= set_event_disc(p1, port1);
  19.221 -    guest_event_notify(cpu_mask);
  19.222 +    evtchn_set_exception(p1, port1);
  19.223  
  19.224   out:
  19.225      if ( p2 != NULL )
  19.226 @@ -243,7 +278,7 @@ static long __event_channel_close(struct
  19.227  }
  19.228  
  19.229  
  19.230 -static long event_channel_close(evtchn_close_t *close)
  19.231 +static long evtchn_close(evtchn_close_t *close)
  19.232  {
  19.233      struct task_struct *p;
  19.234      long                rc;
  19.235 @@ -257,38 +292,36 @@ static long event_channel_close(evtchn_c
  19.236      if ( (p = find_domain_by_id(dom)) == NULL )
  19.237          return -ESRCH;
  19.238  
  19.239 -    rc = __event_channel_close(p, close->port);
  19.240 +    rc = __evtchn_close(p, close->port);
  19.241  
  19.242      put_task_struct(p);
  19.243      return rc;
  19.244  }
  19.245  
  19.246  
  19.247 -static long event_channel_send(int lport)
  19.248 +static long evtchn_send(int lport)
  19.249  {
  19.250      struct task_struct *lp = current, *rp;
  19.251      int                 rport;
  19.252 -    unsigned long       cpu_mask;
  19.253  
  19.254      spin_lock(&lp->event_channel_lock);
  19.255  
  19.256      if ( unlikely(lport < 0) ||
  19.257           unlikely(lport >= lp->max_event_channel) || 
  19.258 -         unlikely(lp->event_channel[lport].state != ECS_CONNECTED) )
  19.259 +         unlikely(lp->event_channel[lport].state != ECS_INTERDOMAIN) )
  19.260      {
  19.261          spin_unlock(&lp->event_channel_lock);
  19.262          return -EINVAL;
  19.263      }
  19.264  
  19.265 -    rp    = lp->event_channel[lport].remote_dom;
  19.266 -    rport = lp->event_channel[lport].remote_port;
  19.267 +    rp    = lp->event_channel[lport].u.remote.dom;
  19.268 +    rport = lp->event_channel[lport].u.remote.port;
  19.269  
  19.270      get_task_struct(rp);
  19.271  
  19.272      spin_unlock(&lp->event_channel_lock);
  19.273  
  19.274 -    cpu_mask = set_event_pending(rp, rport);
  19.275 -    guest_event_notify(cpu_mask);
  19.276 +    evtchn_set_pending(rp, rport);
  19.277  
  19.278      put_task_struct(rp);
  19.279  
  19.280 @@ -296,11 +329,11 @@ static long event_channel_send(int lport
  19.281  }
  19.282  
  19.283  
  19.284 -static long event_channel_status(evtchn_status_t *status)
  19.285 +static long evtchn_status(evtchn_status_t *status)
  19.286  {
  19.287      struct task_struct *p;
  19.288 -    domid_t             dom = status->dom1;
  19.289 -    int                 port = status->port1;
  19.290 +    domid_t             dom = status->dom;
  19.291 +    int                 port = status->port;
  19.292      event_channel_t    *chn;
  19.293  
  19.294      if ( dom == DOMID_SELF )
  19.295 @@ -326,13 +359,21 @@ static long event_channel_status(evtchn_
  19.296      case ECS_FREE:
  19.297          status->status = EVTCHNSTAT_closed;
  19.298          break;
  19.299 -    case ECS_DISCONNECTED:
  19.300 -        status->status = EVTCHNSTAT_disconnected;
  19.301 +    case ECS_UNBOUND:
  19.302 +        status->status = EVTCHNSTAT_unbound;
  19.303 +        break;
  19.304 +    case ECS_INTERDOMAIN:
  19.305 +        status->status = EVTCHNSTAT_interdomain;
  19.306 +        status->u.interdomain.dom  = chn[port].u.remote.dom->domain;
  19.307 +        status->u.interdomain.port = chn[port].u.remote.port;
  19.308          break;
  19.309 -    case ECS_CONNECTED:
  19.310 -        status->status = EVTCHNSTAT_connected;
  19.311 -        status->dom2   = chn[port].remote_dom->domain;
  19.312 -        status->port2  = chn[port].remote_port;
  19.313 +    case ECS_PIRQ:
  19.314 +        status->status = EVTCHNSTAT_pirq;
  19.315 +        status->u.pirq = chn[port].u.pirq;
  19.316 +        break;
  19.317 +    case ECS_VIRQ:
  19.318 +        status->status = EVTCHNSTAT_virq;
  19.319 +        status->u.virq = chn[port].u.virq;
  19.320          break;
  19.321      default:
  19.322          BUG();
  19.323 @@ -353,22 +394,28 @@ long do_event_channel_op(evtchn_op_t *uo
  19.324  
  19.325      switch ( op.cmd )
  19.326      {
  19.327 -    case EVTCHNOP_open:
  19.328 -        rc = event_channel_open(&op.u.open);
  19.329 +    case EVTCHNOP_bind_interdomain:
  19.330 +        rc = evtchn_bind_interdomain(&op.u.bind_interdomain);
  19.331 +        if ( copy_to_user(uop, &op, sizeof(op)) != 0 )
  19.332 +            rc = -EFAULT; /* Cleaning up here would be a mess! */
  19.333 +        break;
  19.334 +
  19.335 +    case EVTCHNOP_bind_virq:
  19.336 +        rc = evtchn_bind_virq(&op.u.bind_virq);
  19.337          if ( copy_to_user(uop, &op, sizeof(op)) != 0 )
  19.338              rc = -EFAULT; /* Cleaning up here would be a mess! */
  19.339          break;
  19.340  
  19.341      case EVTCHNOP_close:
  19.342 -        rc = event_channel_close(&op.u.close);
  19.343 +        rc = evtchn_close(&op.u.close);
  19.344          break;
  19.345  
  19.346      case EVTCHNOP_send:
  19.347 -        rc = event_channel_send(op.u.send.local_port);
  19.348 +        rc = evtchn_send(op.u.send.local_port);
  19.349          break;
  19.350  
  19.351      case EVTCHNOP_status:
  19.352 -        rc = event_channel_status(&op.u.status);
  19.353 +        rc = evtchn_status(&op.u.status);
  19.354          if ( copy_to_user(uop, &op, sizeof(op)) != 0 )
  19.355              rc = -EFAULT;
  19.356          break;
  19.357 @@ -382,13 +429,28 @@ long do_event_channel_op(evtchn_op_t *uo
  19.358  }
  19.359  
  19.360  
  19.361 +int init_event_channels(struct task_struct *p)
  19.362 +{
  19.363 +    spin_lock_init(&p->event_channel_lock);
  19.364 +    p->event_channel = kmalloc(INIT_EVENT_CHANNELS * sizeof(event_channel_t), 
  19.365 +                               GFP_KERNEL);
  19.366 +    if ( unlikely(p->event_channel == NULL) )
  19.367 +        return -ENOMEM;
  19.368 +    p->max_event_channel = INIT_EVENT_CHANNELS;
  19.369 +    memset(p->event_channel, 0, INIT_EVENT_CHANNELS * sizeof(event_channel_t));
  19.370 +    p->event_channel[0].state  = ECS_VIRQ;
  19.371 +    p->event_channel[0].u.virq = VIRQ_ERROR;
  19.372 +    return 0;
  19.373 +}
  19.374 +
  19.375 +
  19.376  void destroy_event_channels(struct task_struct *p)
  19.377  {
  19.378      int i;
  19.379      if ( p->event_channel != NULL )
  19.380      {
  19.381          for ( i = 0; i < p->max_event_channel; i++ )
  19.382 -            (void)__event_channel_close(p, i);
  19.383 +            (void)__evtchn_close(p, i);
  19.384          kfree(p->event_channel);
  19.385      }
  19.386  }
    20.1 --- a/xen/common/kernel.c	Wed Mar 24 19:05:53 2004 +0000
    20.2 +++ b/xen/common/kernel.c	Thu Mar 25 15:02:26 2004 +0000
    20.3 @@ -107,6 +107,7 @@ void cmain(unsigned long magic, multiboo
    20.4      module_t *mod;
    20.5      void *heap_start;
    20.6      int i;
    20.7 +    unsigned long max_mem;
    20.8  
    20.9      /* Parse the command-line options. */
   20.10      cmdline = (unsigned char *)(mbi->cmdline ? __va(mbi->cmdline) : NULL);
   20.11 @@ -193,28 +194,38 @@ void cmain(unsigned long magic, multiboo
   20.12          for ( ; ; ) ;
   20.13      }
   20.14  
   20.15 -    max_page = (mbi->mem_upper+1024) >> (PAGE_SHIFT - 10);
   20.16 +    max_mem = max_page = (mbi->mem_upper+1024) >> (PAGE_SHIFT - 10);
   20.17  
   20.18      /* The array of pfn_info structures must fit into the reserved area. */
   20.19 -    if ( (sizeof(struct pfn_info) * max_page) > 
   20.20 +    if ( (sizeof(struct pfn_info) * max_page) >
   20.21           (FRAMETABLE_VIRT_END - FRAMETABLE_VIRT_START) )
   20.22      {
   20.23 -        unsigned long new_max = 
   20.24 +        unsigned long new_max =
   20.25              (FRAMETABLE_VIRT_END - FRAMETABLE_VIRT_START) /
   20.26              sizeof(struct pfn_info);
   20.27 -	printk("Truncating available memory to %lu/%luMB\n", 
   20.28 +        printk("Truncating available memory to %lu/%luMB\n",
   20.29                 new_max >> (20 - PAGE_SHIFT), max_page >> (20 - PAGE_SHIFT));
   20.30 -	max_page = new_max;
   20.31 +        max_page = new_max;
   20.32      }
   20.33  
   20.34      set_current(&idle0_task);
   20.35  
   20.36      init_frametable(max_page);
   20.37 -    printk("Initialised all memory on a %luMB machine\n",
   20.38 -           max_page >> (20-PAGE_SHIFT));
   20.39 +    printk("Initialised %luMB memory on a %luMB machine\n",
   20.40 +           max_page >> (20-PAGE_SHIFT),
   20.41 +	   max_mem  >> (20-PAGE_SHIFT) );
   20.42  
   20.43      heap_start = memguard_init(&_end);
   20.44  
   20.45 +    printk("Xen heap size is %luKB\n", 
   20.46 +	   (MAX_MONITOR_ADDRESS-__pa(heap_start))/1024 );
   20.47 +
   20.48 +    if ( ((MAX_MONITOR_ADDRESS-__pa(heap_start))/1024) <= 4096 )
   20.49 +    {
   20.50 +        printk("Xen heap size is too small to safely continue!\n");
   20.51 +        for ( ; ; ) ;
   20.52 +    }
   20.53 +
   20.54      init_page_allocator(__pa(heap_start), MAX_MONITOR_ADDRESS);
   20.55   
   20.56      /* Initialise the slab allocator. */
    21.1 --- a/xen/common/keyhandler.c	Wed Mar 24 19:05:53 2004 +0000
    21.2 +++ b/xen/common/keyhandler.c	Thu Mar 25 15:02:26 2004 +0000
    21.3 @@ -99,7 +99,7 @@ static char *task_states[] =
    21.4  
    21.5  void do_task_queues(u_char key, void *dev_id, struct pt_regs *regs) 
    21.6  {
    21.7 -    unsigned long       flags, cpu_mask = 0; 
    21.8 +    unsigned long       flags;
    21.9      struct task_struct *p; 
   21.10      shared_info_t      *s; 
   21.11      s_time_t            now = NOW();
   21.12 @@ -116,15 +116,13 @@ void do_task_queues(u_char key, void *de
   21.13                 p->domain, p->processor, p->has_cpu ? 'T':'F', 
   21.14                 task_states[p->state], p->hyp_events); 
   21.15          s = p->shared_info; 
   21.16 -        printk("Guest: events = %08lx, events_mask = %08lx\n", 
   21.17 -               s->events, s->events_mask); 
   21.18 +        printk("Guest: upcall_pend = %08lx, upcall_mask = %08lx\n", 
   21.19 +               s->evtchn_upcall_pending, s->evtchn_upcall_mask);
   21.20          printk("Notifying guest...\n"); 
   21.21 -        cpu_mask |= mark_guest_event(p, _EVENT_DEBUG);
   21.22 +        send_guest_virq(p, VIRQ_DEBUG);
   21.23      }
   21.24  
   21.25      read_unlock_irqrestore(&tasklist_lock, flags); 
   21.26 -
   21.27 -    guest_event_notify(cpu_mask);
   21.28  }
   21.29  
   21.30  extern void perfc_printall (u_char key, void *dev_id, struct pt_regs *regs);
    22.1 --- a/xen/common/memory.c	Wed Mar 24 19:05:53 2004 +0000
    22.2 +++ b/xen/common/memory.c	Thu Mar 25 15:02:26 2004 +0000
    22.3 @@ -133,6 +133,7 @@
    22.4  #include <xen/errno.h>
    22.5  #include <xen/perfc.h>
    22.6  #include <xen/interrupt.h>
    22.7 +#include <xen/shadow.h>
    22.8  #include <asm/page.h>
    22.9  #include <asm/flushtlb.h>
   22.10  #include <asm/io.h>
   22.11 @@ -182,6 +183,7 @@ static struct {
   22.12      struct task_struct *subject_p;
   22.13  } percpu_info[NR_CPUS] __cacheline_aligned;
   22.14  
   22.15 +
   22.16  /*
   22.17   * init_frametable:
   22.18   * Initialise per-frame memory information. This goes directly after
   22.19 @@ -762,9 +764,25 @@ void free_page_type(struct pfn_info *pag
   22.20      switch ( type )
   22.21      {
   22.22      case PGT_l1_page_table:
   22.23 -        return free_l1_table(page);
   22.24 +        free_l1_table(page);
   22.25 +	if ( unlikely(current->mm.shadow_mode) && 
   22.26 +	     (get_shadow_status(current, page-frame_table) & PSH_shadowed) )
   22.27 +	{
   22.28 +	    unshadow_table( page-frame_table, type );
   22.29 +	    put_shadow_status(current);
   22.30 +        }
   22.31 +	return;
   22.32 +
   22.33      case PGT_l2_page_table:
   22.34 -        return free_l2_table(page);
   22.35 +        free_l2_table(page);
   22.36 +	if ( unlikely(current->mm.shadow_mode) && 
   22.37 +	     (get_shadow_status(current, page-frame_table) & PSH_shadowed) )
   22.38 +	{
   22.39 +	    unshadow_table( page-frame_table, type );
   22.40 +	    put_shadow_status(current);
   22.41 +        }
   22.42 +	return;
   22.43 +
   22.44      default:
   22.45          BUG();
   22.46      }
   22.47 @@ -831,11 +849,22 @@ static int do_extended_command(unsigned 
   22.48          if ( likely(okay) )
   22.49          {
   22.50              invalidate_shadow_ldt();
   22.51 +
   22.52              percpu_info[cpu].deferred_ops &= ~DOP_FLUSH_TLB;
   22.53              old_base_pfn = pagetable_val(current->mm.pagetable) >> PAGE_SHIFT;
   22.54              current->mm.pagetable = mk_pagetable(pfn << PAGE_SHIFT);
   22.55 -            write_cr3_counted(pfn << PAGE_SHIFT);
   22.56 -            put_page_and_type(&frame_table[old_base_pfn]);
   22.57 +
   22.58 +            if( unlikely(current->mm.shadow_mode))
   22.59 +            {
   22.60 +                current->mm.shadow_table = 
   22.61 +                    shadow_mk_pagetable(current, pfn<<PAGE_SHIFT);
   22.62 +                write_cr3_counted(pagetable_val(current->mm.shadow_table));
   22.63 +            }
   22.64 +            else
   22.65 +            {
   22.66 +                write_cr3_counted(pfn << PAGE_SHIFT);
   22.67 +            }
   22.68 +            put_page_and_type(&frame_table[old_base_pfn]);    
   22.69          }
   22.70          else
   22.71          {
   22.72 @@ -919,6 +948,8 @@ int do_mmu_update(mmu_update_t *ureqs, i
   22.73      struct pfn_info *page;
   22.74      int rc = 0, okay = 1, i, cpu = smp_processor_id();
   22.75      unsigned int cmd;
   22.76 +    unsigned long prev_spfn = 0;
   22.77 +    l1_pgentry_t *prev_spl1e = 0;
   22.78  
   22.79      perfc_incrc(calls_to_mmu_update); 
   22.80      perfc_addc(num_page_updates, count);
   22.81 @@ -969,6 +1000,16 @@ int do_mmu_update(mmu_update_t *ureqs, i
   22.82                  {
   22.83                      okay = mod_l1_entry((l1_pgentry_t *)va, 
   22.84                                          mk_l1_pgentry(req.val)); 
   22.85 +
   22.86 +		    if ( okay && unlikely(current->mm.shadow_mode) &&
   22.87 +			 (get_shadow_status(current, page-frame_table) &
   22.88 +			  PSH_shadowed) )
   22.89 +		    {
   22.90 +		        shadow_l1_normal_pt_update( req.ptr, req.val, 
   22.91 +						    &prev_spfn, &prev_spl1e );
   22.92 +			put_shadow_status(current);
   22.93 +		    }
   22.94 +
   22.95                      put_page_type(page);
   22.96                  }
   22.97                  break;
   22.98 @@ -978,6 +1019,15 @@ int do_mmu_update(mmu_update_t *ureqs, i
   22.99                      okay = mod_l2_entry((l2_pgentry_t *)va, 
  22.100                                          mk_l2_pgentry(req.val),
  22.101                                          pfn); 
  22.102 +
  22.103 +		    if ( okay && unlikely(current->mm.shadow_mode) &&
  22.104 +			 (get_shadow_status(current, page-frame_table) & 
  22.105 +			  PSH_shadowed) )
  22.106 +		    {
  22.107 +		        shadow_l2_normal_pt_update( req.ptr, req.val );
  22.108 +			put_shadow_status(current);
  22.109 +		    }
  22.110 +
  22.111                      put_page_type(page);
  22.112                  }
  22.113                  break;
  22.114 @@ -987,10 +1037,12 @@ int do_mmu_update(mmu_update_t *ureqs, i
  22.115                      *(unsigned long *)va = req.val;
  22.116                      okay = 1;
  22.117                      put_page_type(page);
  22.118 +
  22.119 +                    // at present, we don't shadowing such pages
  22.120                  }
  22.121                  break;
  22.122              }
  22.123 -            
  22.124 +
  22.125              put_page(page);
  22.126  
  22.127              break;
  22.128 @@ -1033,11 +1085,23 @@ int do_mmu_update(mmu_update_t *ureqs, i
  22.129      if ( prev_pfn != 0 )
  22.130          unmap_domain_mem((void *)va);
  22.131  
  22.132 +    if( prev_spl1e != 0 ) 
  22.133 +        unmap_domain_mem((void *)prev_spl1e);
  22.134 +
  22.135      deferred_ops = percpu_info[cpu].deferred_ops;
  22.136      percpu_info[cpu].deferred_ops = 0;
  22.137  
  22.138      if ( deferred_ops & DOP_FLUSH_TLB )
  22.139 -        write_cr3_counted(pagetable_val(current->mm.pagetable));
  22.140 +    {
  22.141 +        if ( unlikely(current->mm.shadow_mode) )
  22.142 +	{
  22.143 +            check_pagetable( current, 
  22.144 +			     current->mm.pagetable, "pre-stlb-flush" );
  22.145 +	    write_cr3_counted(pagetable_val(current->mm.shadow_table));
  22.146 +        }
  22.147 +        else
  22.148 +  	    write_cr3_counted(pagetable_val(current->mm.pagetable));
  22.149 +    }
  22.150  
  22.151      if ( deferred_ops & DOP_RELOAD_LDT )
  22.152          (void)map_ldt_shadow_page(0);
  22.153 @@ -1061,19 +1125,58 @@ int do_update_va_mapping(unsigned long p
  22.154      unsigned int cpu = p->processor;
  22.155      unsigned long deferred_ops;
  22.156  
  22.157 +    perfc_incrc(calls_to_update_va);
  22.158 +
  22.159      if ( unlikely(page_nr >= (HYPERVISOR_VIRT_START >> PAGE_SHIFT)) )
  22.160          return -EINVAL;
  22.161  
  22.162 +    // XXX when we make this support 4MB pages we should also
  22.163 +    // deal with the case of updating L2s
  22.164 +
  22.165      if ( unlikely(!mod_l1_entry(&linear_pg_table[page_nr], 
  22.166                                  mk_l1_pgentry(val))) )
  22.167          err = -EINVAL;
  22.168  
  22.169 +    if ( unlikely(p->mm.shadow_mode) )
  22.170 +    {
  22.171 +        unsigned long sval = 0;
  22.172 +
  22.173 +	// XXX this only works for l1 entries, with no translation
  22.174 +
  22.175 +        if ( (val & _PAGE_PRESENT) && (val & _PAGE_ACCESSED) )
  22.176 +        {
  22.177 +	    sval = val;
  22.178 +            if ( !(val & _PAGE_DIRTY) ) 
  22.179 +	        sval &= ~_PAGE_RW;
  22.180 +	}
  22.181 +
  22.182 +	/*	printk("update_va_map: page_nr=%08lx val =%08lx sval =%08lx\n", 
  22.183 +	       page_nr, val, sval);*/
  22.184 +
  22.185 +	if ( __put_user( sval, ((unsigned long *) (&shadow_linear_pg_table[page_nr])) ) )
  22.186 +	{
  22.187 +	    // Since L2's are guranteed RW, failure indicates the page
  22.188 +	    // was not shadowed, so ignore.
  22.189 +            perfc_incrc(shadow_update_va_fail);
  22.190 +	    //MEM_LOG("update_va_map: couldn't write update\n");	
  22.191 +	}
  22.192 +
  22.193 +	check_pagetable( p, p->mm.pagetable, "va" ); // debug
  22.194 +    
  22.195 +    }
  22.196 +
  22.197 +
  22.198      deferred_ops = percpu_info[cpu].deferred_ops;
  22.199      percpu_info[cpu].deferred_ops = 0;
  22.200  
  22.201      if ( unlikely(deferred_ops & DOP_FLUSH_TLB) || 
  22.202           unlikely(flags & UVMF_FLUSH_TLB) )
  22.203 -        write_cr3_counted(pagetable_val(p->mm.pagetable));
  22.204 +    {
  22.205 +        if ( unlikely(p->mm.shadow_mode) )
  22.206 +            write_cr3_counted(pagetable_val(p->mm.shadow_table));
  22.207 +        else
  22.208 +            write_cr3_counted(pagetable_val(p->mm.pagetable));
  22.209 +    }
  22.210      else if ( unlikely(flags & UVMF_INVLPG) )
  22.211          __flush_tlb_one(page_nr << PAGE_SHIFT);
  22.212  
    23.1 --- a/xen/common/perfc.c	Wed Mar 24 19:05:53 2004 +0000
    23.2 +++ b/xen/common/perfc.c	Thu Mar 25 15:02:26 2004 +0000
    23.3 @@ -8,12 +8,20 @@
    23.4  #undef  PERFCOUNTER
    23.5  #undef  PERFCOUNTER_CPU
    23.6  #undef  PERFCOUNTER_ARRAY
    23.7 +#undef  PERFSTATUS
    23.8 +#undef  PERFSTATUS_CPU
    23.9 +#undef  PERFSTATUS_ARRAY
   23.10  #define PERFCOUNTER( var, name )              { name, TYPE_SINGLE, 0 },
   23.11  #define PERFCOUNTER_CPU( var, name )          { name, TYPE_CPU,    0 },
   23.12  #define PERFCOUNTER_ARRAY( var, name, size )  { name, TYPE_ARRAY,  size },
   23.13 +#define PERFSTATUS( var, name )               { name, TYPE_S_SINGLE, 0 },
   23.14 +#define PERFSTATUS_CPU( var, name )           { name, TYPE_S_CPU,    0 },
   23.15 +#define PERFSTATUS_ARRAY( var, name, size )   { name, TYPE_S_ARRAY,  size },
   23.16  static struct {
   23.17      char *name;
   23.18 -    enum { TYPE_SINGLE, TYPE_CPU, TYPE_ARRAY } type;
   23.19 +    enum { TYPE_SINGLE, TYPE_CPU, TYPE_ARRAY,
   23.20 +	   TYPE_S_SINGLE, TYPE_S_CPU, TYPE_S_ARRAY
   23.21 +    } type;
   23.22      int nr_elements;
   23.23  } perfc_info[] = {
   23.24  #include <xen/perfc_defn.h>
   23.25 @@ -38,10 +46,12 @@ void perfc_printall(u_char key, void *de
   23.26          switch ( perfc_info[i].type )
   23.27          {
   23.28          case TYPE_SINGLE:
   23.29 +        case TYPE_S_SINGLE:
   23.30              printk("TOTAL[%10d]", atomic_read(&counters[0]));
   23.31              counters += 1;
   23.32              break;
   23.33          case TYPE_CPU:
   23.34 +        case TYPE_S_CPU:
   23.35              for ( j = sum = 0; j < smp_num_cpus; j++ )
   23.36                  sum += atomic_read(&counters[j]);
   23.37              printk("TOTAL[%10d]  ", sum);
   23.38 @@ -50,6 +60,7 @@ void perfc_printall(u_char key, void *de
   23.39              counters += NR_CPUS;
   23.40              break;
   23.41          case TYPE_ARRAY:
   23.42 +        case TYPE_S_ARRAY:
   23.43              for ( j = sum = 0; j < perfc_info[i].nr_elements; j++ )
   23.44                  sum += atomic_read(&counters[j]);
   23.45              printk("TOTAL[%10d]  ", sum);
   23.46 @@ -64,9 +75,37 @@ void perfc_printall(u_char key, void *de
   23.47  
   23.48  void perfc_reset(u_char key, void *dev_id, struct pt_regs *regs)
   23.49  {
   23.50 +    int i, j, sum;
   23.51      s_time_t now = NOW();
   23.52 +    atomic_t *counters = (atomic_t *)&perfcounters;
   23.53 +
   23.54      printk("Xen performance counters RESET (now = 0x%08X:%08X)\n",
   23.55             (u32)(now>>32), (u32)now);
   23.56 -    memset(&perfcounters, 0, sizeof(perfcounters));
   23.57 +
   23.58 +    // leave STATUS counters alone -- don't reset
   23.59 +
   23.60 +    for ( i = 0; i < NR_PERFCTRS; i++ ) 
   23.61 +    {
   23.62 +        switch ( perfc_info[i].type )
   23.63 +        {
   23.64 +        case TYPE_SINGLE:
   23.65 +	    atomic_set(&counters[0],0);
   23.66 +        case TYPE_S_SINGLE:
   23.67 +            counters += 1;
   23.68 +            break;
   23.69 +        case TYPE_CPU:
   23.70 +            for ( j = sum = 0; j < smp_num_cpus; j++ )
   23.71 +	      	atomic_set(&counters[j],0);
   23.72 +        case TYPE_S_CPU:
   23.73 +            counters += NR_CPUS;
   23.74 +            break;
   23.75 +        case TYPE_ARRAY:
   23.76 +            for ( j = sum = 0; j < perfc_info[i].nr_elements; j++ )
   23.77 +	      	atomic_set(&counters[j],0);
   23.78 +        case TYPE_S_ARRAY:
   23.79 +            counters += perfc_info[i].nr_elements;
   23.80 +            break;
   23.81 +        }
   23.82 +    }
   23.83  }
   23.84  
    24.1 --- a/xen/common/physdev.c	Wed Mar 24 19:05:53 2004 +0000
    24.2 +++ b/xen/common/physdev.c	Thu Mar 25 15:02:26 2004 +0000
    24.3 @@ -576,28 +576,16 @@ static long pci_find_irq(int seg, int bu
    24.4  static void phys_dev_interrupt(int irq, void *dev_id, struct pt_regs *ptregs)
    24.5  {
    24.6      phys_dev_t          *pdev;
    24.7 -    struct task_struct  *p;
    24.8 -    unsigned long cpu_mask = 0;
    24.9  
   24.10 -    if ( !(pdev = (phys_dev_t *)dev_id) )
   24.11 +    if ( (pdev = (phys_dev_t *)dev_id) == NULL )
   24.12      {
   24.13          printk("spurious interrupt, no proper device id, %d\n", irq);
   24.14          return;
   24.15      }
   24.16      
   24.17 -    p = pdev->owner;
   24.18 -
   24.19 -    if ( test_bit(irq, &p->shared_info->physirq_pend) )
   24.20 -    {
   24.21 -        /* Some interrupt already delivered to guest */
   24.22 -        return;
   24.23 -    }
   24.24 -
   24.25 -    /* notify guest */
   24.26 -    set_bit(irq, &p->shared_info->physirq_pend);
   24.27 +    /* XXX KAF: introduced race here? */
   24.28      set_bit(ST_IRQ_DELIVERED, &pdev->state);
   24.29 -    cpu_mask |= mark_guest_event(p, _EVENT_PHYSIRQ);
   24.30 -    guest_event_notify(cpu_mask);
   24.31 +    send_guest_pirq(pdev->owner, irq);
   24.32  }
   24.33  
   24.34  /* this is called instead of the PICs original end handler. 
   24.35 @@ -767,11 +755,13 @@ static long pci_finished_irq(int irq)
   24.36          return -EINVAL;
   24.37      }
   24.38  
   24.39 +#if 0 /* XXX KAF: do we need this? */
   24.40      if ( test_bit(irq, &current->shared_info->physirq_pend) )
   24.41      {
   24.42          printk("finished_irq called for un-acknowleged irq %d\n", irq);        
   24.43          return -EINVAL;
   24.44      }
   24.45 +#endif
   24.46  
   24.47      clear_bit(ST_IRQ_DELIVERED, &pdev->state);
   24.48  
    25.1 --- a/xen/common/schedule.c	Wed Mar 24 19:05:53 2004 +0000
    25.2 +++ b/xen/common/schedule.c	Thu Mar 25 15:02:26 2004 +0000
    25.3 @@ -217,7 +217,7 @@ void wake_up(struct task_struct *p)
    25.4  static long do_block(void)
    25.5  {
    25.6      ASSERT(current->domain != IDLE_DOMAIN_ID);
    25.7 -    set_bit(EVENTS_MASTER_ENABLE_BIT, &current->shared_info->events_mask);
    25.8 +    clear_bit(0, &current->shared_info->evtchn_upcall_mask);
    25.9      current->state = TASK_INTERRUPTIBLE;
   25.10      TRACE_2D(TRC_SCHED_BLOCK, current->domain, current);
   25.11      __enter_scheduler();
   25.12 @@ -379,7 +379,7 @@ long sched_adjdom(struct sched_adjdom_cm
   25.13   */
   25.14  unsigned long __reschedule(struct task_struct *p)
   25.15  {
   25.16 -       int cpu = p->processor;
   25.17 +    int cpu = p->processor;
   25.18      struct task_struct *curr;
   25.19      s_time_t now, min_time;
   25.20  
   25.21 @@ -413,9 +413,13 @@ void reschedule(struct task_struct *p)
   25.22  
   25.23      spin_lock_irqsave(&schedule_lock[p->processor], flags);
   25.24      cpu_mask = __reschedule(p);
   25.25 +    spin_unlock_irqrestore(&schedule_lock[p->processor], flags);
   25.26  
   25.27 -    spin_unlock_irqrestore(&schedule_lock[p->processor], flags);
   25.28 -    hyp_event_notify(cpu_mask);
   25.29 +#ifdef CONFIG_SMP
   25.30 +    cpu_mask &= ~(1 << smp_processor_id());
   25.31 +    if ( cpu_mask != 0 )
   25.32 +        smp_send_event_check_mask(cpu_mask);
   25.33 +#endif
   25.34  }
   25.35  
   25.36  /* 
   25.37 @@ -517,7 +521,7 @@ asmlinkage void __enter_scheduler(void)
   25.38  
   25.39      /* Mark a timer event for the newly-scheduled domain. */
   25.40      if ( !is_idle_task(next) )
   25.41 -        set_bit(_EVENT_TIMER, &next->shared_info->events);
   25.42 +        evtchn_set_pending(next, VIRQ_TIMER);
   25.43      
   25.44      schedule_tail(next);
   25.45  
   25.46 @@ -556,8 +560,8 @@ static void t_timer_fn(unsigned long unu
   25.47  
   25.48      TRACE_0D(TRC_SCHED_T_TIMER_FN);
   25.49  
   25.50 -    if ( !is_idle_task(p) ) 
   25.51 -        set_bit(_EVENT_TIMER, &p->shared_info->events);
   25.52 +    if ( !is_idle_task(p) )
   25.53 +        send_guest_virq(p, VIRQ_TIMER);
   25.54  
   25.55      t_timer[p->processor].expires = NOW() + MILLISECS(10);
   25.56      add_ac_timer(&t_timer[p->processor]);
   25.57 @@ -566,13 +570,9 @@ static void t_timer_fn(unsigned long unu
   25.58  /* Domain timer function, sends a virtual timer interrupt to domain */
   25.59  static void dom_timer_fn(unsigned long data)
   25.60  {
   25.61 -    unsigned long cpu_mask = 0;
   25.62      struct task_struct *p = (struct task_struct *)data;
   25.63 -
   25.64      TRACE_0D(TRC_SCHED_DOM_TIMER_FN);
   25.65 -
   25.66 -    cpu_mask |= mark_guest_event(p, _EVENT_TIMER);
   25.67 -    guest_event_notify(cpu_mask);
   25.68 +    send_guest_virq(p, VIRQ_TIMER);
   25.69  }
   25.70  
   25.71  
    26.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    26.2 +++ b/xen/common/shadow.c	Thu Mar 25 15:02:26 2004 +0000
    26.3 @@ -0,0 +1,815 @@
    26.4 +/* -*-  Mode:C; c-basic-offset:4; tab-width:4 -*- */
    26.5 +
    26.6 +#include <xen/config.h>
    26.7 +#include <xen/types.h>
    26.8 +#include <xen/mm.h>
    26.9 +#include <xen/shadow.h>
   26.10 +#include <asm/domain_page.h>
   26.11 +#include <asm/page.h>
   26.12 +
   26.13 +
   26.14 +/********
   26.15 +
   26.16 +To use these shadow page tables, guests must not rely on the ACCESSED
   26.17 +and DIRTY bits on L2 pte's being accurate -- they will typically all be set.
   26.18 +
   26.19 +I doubt this will break anything. (If guests want to use the va_update
   26.20 +mechanism they've signed up for this anyhow...)
   26.21 +
   26.22 +There's a per-domain shadow table spin lock which works fine for SMP
   26.23 +hosts. We don't have to worry about interrupts as no shadow operations
   26.24 +happen in an interrupt context. It's probably not quite ready for SMP
   26.25 +guest operation as we have to worry about synchonisation between gpte
   26.26 +and spte updates. Its possible that this might only happen in a
   26.27 +hypercall context, in which case we'll probably at have a per-domain
   26.28 +hypercall lock anyhow (at least initially).
   26.29 +
   26.30 +********/
   26.31 +
   26.32 +int shadow_mode_control( struct task_struct *p, unsigned int op )
   26.33 +{
   26.34 +	if (p->mm.shadow_mode && op == DOM0_SHADOW_CONTROL_OP_OFF )
   26.35 +    {
   26.36 +		shadow_mode_disable(p);
   26.37 +	}
   26.38 +	else if (p->mm.shadow_mode && op == DOM0_SHADOW_CONTROL_OP_ENABLE_TEST )
   26.39 +	{
   26.40 +        shadow_mode_disable(p);
   26.41 +        shadow_mode_enable(p, SHM_test);
   26.42 +	}	
   26.43 +	else if (p->mm.shadow_mode && op == DOM0_SHADOW_CONTROL_OP_FLUSH )
   26.44 +    {
   26.45 +		//shadow_mode_flush(p);
   26.46 +    }
   26.47 +	else
   26.48 +    {
   26.49 +		return -EINVAL;
   26.50 +    }
   26.51 +
   26.52 +	return 0;
   26.53 +}
   26.54 +
   26.55 +int shadow_mode_enable( struct task_struct *p, unsigned int mode )
   26.56 +{
   26.57 +	struct shadow_status **fptr;
   26.58 +	int i;
   26.59 +
   26.60 +	// sychronously stop domain
   26.61 +    // XXX for the moment, only use on already stopped domains!!!
   26.62 +
   26.63 +	spin_lock_init(&p->mm.shadow_lock);
   26.64 +	spin_lock(&p->mm.shadow_lock);
   26.65 +
   26.66 +    p->mm.shadow_mode = mode;
   26.67 +	
   26.68 +	// allocate hashtable
   26.69 +    p->mm.shadow_ht = kmalloc( shadow_ht_buckets * 
   26.70 +							   sizeof(struct shadow_status), GFP_KERNEL );
   26.71 +	if( ! p->mm.shadow_ht )
   26.72 +		goto nomem;
   26.73 +
   26.74 +	memset( p->mm.shadow_ht, 0, shadow_ht_buckets * 
   26.75 +							   sizeof(struct shadow_status) );
   26.76 +
   26.77 +
   26.78 +	// allocate space for first lot of extra nodes
   26.79 +    p->mm.shadow_ht_extras = kmalloc( sizeof(void*) + (shadow_ht_extra_size * 
   26.80 +							   sizeof(struct shadow_status)), GFP_KERNEL );
   26.81 +
   26.82 +	if( ! p->mm.shadow_ht_extras )
   26.83 +		goto nomem;
   26.84 +
   26.85 +	memset( p->mm.shadow_ht_extras, 0, sizeof(void*) + (shadow_ht_extra_size * 
   26.86 +							   sizeof(struct shadow_status)) );
   26.87 +	
   26.88 +    // add extras to free list
   26.89 +	fptr = &p->mm.shadow_ht_free;
   26.90 +	for ( i=0; i<shadow_ht_extra_size; i++ )
   26.91 +	{
   26.92 +		*fptr = &p->mm.shadow_ht_extras[i];
   26.93 +		fptr = &(p->mm.shadow_ht_extras[i].next);
   26.94 +	}
   26.95 +	*fptr = NULL;
   26.96 +	*((struct shadow_status ** ) &p->mm.shadow_ht_extras[shadow_ht_extra_size]) = NULL;
   26.97 +
   26.98 +	spin_unlock(&p->mm.shadow_lock);
   26.99 +
  26.100 +    // call shadow_mk_pagetable
  26.101 +	p->mm.shadow_table = shadow_mk_pagetable( p, 
  26.102 +											  pagetable_val(p->mm.pagetable) );
  26.103 +
  26.104 +	return 0;
  26.105 +
  26.106 +nomem:
  26.107 +	spin_unlock(&p->mm.shadow_lock);
  26.108 +	return -ENOMEM;
  26.109 +}
  26.110 +
  26.111 +void shadow_mode_disable( )
  26.112 +{
  26.113 +
  26.114 +    // free the hash buckets as you go
  26.115 +
  26.116 +    // free the hashtable itself
  26.117 +}
  26.118 +
  26.119 +
  26.120 +static inline void free_shadow_page( struct task_struct *p, unsigned int pfn )
  26.121 +{
  26.122 +    unsigned long flags;
  26.123 +
  26.124 +	p->mm.shadow_page_count--;
  26.125 +
  26.126 +    spin_lock_irqsave(&free_list_lock, flags);
  26.127 +    list_add(&frame_table[pfn].list, &free_list);
  26.128 +    free_pfns++;
  26.129 +    spin_unlock_irqrestore(&free_list_lock, flags);
  26.130 +}
  26.131 +
  26.132 +static inline struct pfn_info *alloc_shadow_page( struct task_struct *p )
  26.133 +{
  26.134 +	p->mm.shadow_page_count++;
  26.135 +
  26.136 +	return alloc_domain_page( NULL );
  26.137 +}
  26.138 +
  26.139 +
  26.140 +static void __free_shadow_table( struct task_struct *p )
  26.141 +{
  26.142 +	int j;
  26.143 +	struct shadow_status *a;
  26.144 +	
  26.145 +	// the code assumes you're not using the page tables i.e.
  26.146 +    // the domain is stopped and cr3 is something else!!
  26.147 +
  26.148 +    // walk the hash table and call free_shadow_page on all pages
  26.149 +
  26.150 +    for(j=0;j<shadow_ht_buckets;j++)
  26.151 +    {
  26.152 +        a = &p->mm.shadow_ht[j];        
  26.153 +        if (a->pfn)
  26.154 +        {
  26.155 +            free_shadow_page( p, a->spfn_and_flags & PSH_pfn_mask );
  26.156 +            a->pfn = 0;
  26.157 +            a->spfn_and_flags = 0;
  26.158 +        }
  26.159 +        a=a->next;
  26.160 +        while(a)
  26.161 +		{ 
  26.162 +            struct shadow_status *next = a->next;
  26.163 +            free_shadow_page( p, a->spfn_and_flags & PSH_pfn_mask );
  26.164 +            a->pfn = 0;
  26.165 +            a->spfn_and_flags = 0;
  26.166 +            a->next = p->mm.shadow_ht_free;
  26.167 +            p->mm.shadow_ht_free = a;
  26.168 +            a=next;
  26.169 +		}
  26.170 +	}
  26.171 +}
  26.172 +
  26.173 +static void flush_shadow_table( struct task_struct *p )
  26.174 +{
  26.175 +	
  26.176 +    // XXX synchronously stop domain (needed for SMP guests)
  26.177 +
  26.178 +    // switch to idle task's page tables
  26.179 + 
  26.180 +    // walk the hash table and call free_shadow_page on all pages
  26.181 +	spin_lock(&p->mm.shadow_lock);
  26.182 +	__free_shadow_table( p );
  26.183 +	spin_unlock(&p->mm.shadow_lock);
  26.184 +
  26.185 +    // XXX unpause domain
  26.186 +}
  26.187 +
  26.188 +
  26.189 +
  26.190 +void unshadow_table( unsigned long gpfn, unsigned int type )
  26.191 +{
  26.192 +	unsigned long spfn;
  26.193 +
  26.194 +    SH_VLOG("unshadow_table type=%08x gpfn=%08lx",
  26.195 +		 type,
  26.196 +		 gpfn );
  26.197 +
  26.198 +	perfc_incrc(unshadow_table_count);
  26.199 +
  26.200 +	// this function is the same for both l1 and l2 tables
  26.201 +
  26.202 +	// even in the SMP guest case, there won't be a race here as
  26.203 +    // this CPU was the one that cmpxchg'ed the page to invalid
  26.204 +
  26.205 +	spfn = __shadow_status(current, gpfn) & PSH_pfn_mask;
  26.206 +	delete_shadow_status(current, gpfn);
  26.207 +
  26.208 +#if 0 // XXX leave as might be useful for later debugging
  26.209 +	{ 
  26.210 +		int i;
  26.211 +		unsigned long * spl1e = map_domain_mem( spfn<<PAGE_SHIFT );
  26.212 +
  26.213 +		for ( i = 0; i < ENTRIES_PER_L1_PAGETABLE; i++ )
  26.214 +	        {
  26.215 +				spl1e[i] = 0xdead0000;
  26.216 +			}
  26.217 +		unmap_domain_mem( spl1e );
  26.218 +	}
  26.219 +#endif
  26.220 +
  26.221 +	if (type == PGT_l1_page_table)
  26.222 +		perfc_decr(shadow_l1_pages);
  26.223 +    else
  26.224 +		perfc_decr(shadow_l2_pages);
  26.225 +
  26.226 +	free_shadow_page( current, spfn );
  26.227 +
  26.228 +}
  26.229 +
  26.230 +
  26.231 +static unsigned long shadow_l2_table( 
  26.232 +                     struct task_struct *p, unsigned long gpfn )
  26.233 +{
  26.234 +	struct pfn_info *spfn_info;
  26.235 +	unsigned long spfn;
  26.236 +	l2_pgentry_t *spl2e, *gpl2e;
  26.237 +	int i;
  26.238 +
  26.239 +	SH_VVLOG("shadow_l2_table( %08lx )",gpfn);
  26.240 +	spin_lock(&p->mm.shadow_lock);
  26.241 +
  26.242 +	perfc_incrc(shadow_l2_table_count);
  26.243 +	perfc_incr(shadow_l2_pages);
  26.244 +
  26.245 +    // XXX in future, worry about racing in SMP guests 
  26.246 +    //      -- use cmpxchg with PSH_pending flag to show progress (and spin)
  26.247 +
  26.248 +	spfn_info = alloc_shadow_page(p);
  26.249 +
  26.250 +    ASSERT( spfn_info ); // XXX deal with failure later e.g. blow cache
  26.251 +
  26.252 +	spfn = (unsigned long) (spfn_info - frame_table);
  26.253 +
  26.254 +	// mark pfn as being shadowed, update field to point at shadow
  26.255 +	set_shadow_status(p, gpfn, spfn | PSH_shadowed);
  26.256 +	
  26.257 +	// we need to do this before the linear map is set up
  26.258 +	spl2e = (l2_pgentry_t *) map_domain_mem(spfn << PAGE_SHIFT);
  26.259 +
  26.260 +	// get hypervisor and 2x linear PT mapings installed 
  26.261 +	memcpy(&spl2e[DOMAIN_ENTRIES_PER_L2_PAGETABLE], 
  26.262 +           &idle_pg_table[DOMAIN_ENTRIES_PER_L2_PAGETABLE],
  26.263 +           HYPERVISOR_ENTRIES_PER_L2_PAGETABLE * sizeof(l2_pgentry_t));
  26.264 +    spl2e[LINEAR_PT_VIRT_START >> L2_PAGETABLE_SHIFT] =
  26.265 +        mk_l2_pgentry((gpfn << PAGE_SHIFT) | __PAGE_HYPERVISOR);
  26.266 +    spl2e[SH_LINEAR_PT_VIRT_START >> L2_PAGETABLE_SHIFT] =
  26.267 +        mk_l2_pgentry((spfn << PAGE_SHIFT) | __PAGE_HYPERVISOR);
  26.268 +    spl2e[PERDOMAIN_VIRT_START >> L2_PAGETABLE_SHIFT] =
  26.269 +        mk_l2_pgentry(__pa(frame_table[gpfn].u.domain->mm.perdomain_pt) | 
  26.270 +                      __PAGE_HYPERVISOR);
  26.271 +
  26.272 +	// can't use the linear map as we may not be in the right PT
  26.273 +	gpl2e = (l2_pgentry_t *) map_domain_mem(gpfn << PAGE_SHIFT);
  26.274 +
  26.275 +	// proactively create entries for pages that are already shadowed
  26.276 +	for ( i = 0; i < DOMAIN_ENTRIES_PER_L2_PAGETABLE; i++ )
  26.277 +	{
  26.278 +		unsigned long spte = 0;
  26.279 +
  26.280 +#if 0  // Turns out this doesn't really help
  26.281 +        unsigned long gpte;
  26.282 +
  26.283 +        gpte = l2_pgentry_val(gpl2e[i]);
  26.284 +
  26.285 +		if (gpte & _PAGE_PRESENT)
  26.286 +		{
  26.287 +			unsigned long s_sh = 
  26.288 +				__shadow_status(p, gpte>>PAGE_SHIFT);
  26.289 +
  26.290 +			if( s_sh & PSH_shadowed ) // PSH_shadowed
  26.291 +			{
  26.292 +				if ( unlikely( (__shadow_status(p, gpte>>PAGE_SHIFT) & PGT_type_mask) == PGT_l2_page_table) )
  26.293 +                {
  26.294 +					printk("Linear mapping detected\n");
  26.295 +  				    spte = gpte & ~_PAGE_RW;
  26.296 +                }
  26.297 +				else
  26.298 +                {
  26.299 +  				    spte = ( gpte & ~PAGE_MASK ) | (s_sh<<PAGE_SHIFT) |
  26.300 +						_PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED ;
  26.301 +				}
  26.302 +				// XXX should probably update guest to ACCESSED|DIRTY too...
  26.303 +
  26.304 +		    }
  26.305 +
  26.306 +		}
  26.307 +#endif
  26.308 +
  26.309 +		spl2e[i] = mk_l2_pgentry( spte );
  26.310 +
  26.311 +	}
  26.312 +
  26.313 +	// its arguable we should 'preemptively shadow' a few active L1 pages
  26.314 +    // to avoid taking a string of faults when 'jacking' a running domain
  26.315 +
  26.316 +    unmap_domain_mem( gpl2e );
  26.317 +    unmap_domain_mem( spl2e );
  26.318 +
  26.319 +	SH_VLOG("shadow_l2_table( %08lx -> %08lx)",gpfn,spfn);
  26.320 +
  26.321 +	spin_unlock(&p->mm.shadow_lock);
  26.322 +	return spfn;
  26.323 +}
  26.324 +
  26.325 +pagetable_t shadow_mk_pagetable( struct task_struct *p, 
  26.326 +											   unsigned long gptbase)
  26.327 +{
  26.328 +	unsigned long gpfn, spfn=0;
  26.329 +
  26.330 +	SH_VVLOG("shadow_mk_pagetable( gptbase=%08lx, mode=%d )",
  26.331 +			 gptbase, p->mm.shadow_mode );
  26.332 +
  26.333 +	if ( likely(p->mm.shadow_mode) )  // should always be true if we're here
  26.334 +	{
  26.335 +		gpfn =  gptbase >> PAGE_SHIFT;
  26.336 +		
  26.337 +		if ( unlikely((spfn=__shadow_status(p, gpfn)) == 0 ) )
  26.338 +		{
  26.339 +			spfn = shadow_l2_table(p, gpfn );
  26.340 +		}      
  26.341 +	}
  26.342 +
  26.343 +	SH_VVLOG("leaving shadow_mk_pagetable( gptbase=%08lx, mode=%d )",
  26.344 +			 gptbase, p->mm.shadow_mode );
  26.345 +
  26.346 +	return mk_pagetable(spfn<<PAGE_SHIFT);
  26.347 +}
  26.348 +
  26.349 +int shadow_fault( unsigned long va, long error_code )
  26.350 +{
  26.351 +	unsigned long gpte, spte;
  26.352 +
  26.353 +	SH_VVLOG("shadow_fault( va=%08lx, code=%ld )", va, error_code );
  26.354 +
  26.355 +    check_pagetable( current, current->mm.pagetable, "pre-sf" );
  26.356 +
  26.357 +	if ( unlikely(__get_user(gpte, (unsigned long*)&linear_pg_table[va>>PAGE_SHIFT])) )
  26.358 +	{
  26.359 +		SH_VVLOG("shadow_fault - EXIT: read gpte faulted" );
  26.360 +		return 0;  // propagate to guest
  26.361 +	}
  26.362 +
  26.363 +	if ( ! (gpte & _PAGE_PRESENT) )
  26.364 +	{
  26.365 +		SH_VVLOG("shadow_fault - EXIT: gpte not present (%lx)",gpte );
  26.366 +		return 0;  // we're not going to be able to help
  26.367 +    }
  26.368 +
  26.369 +    if ( (error_code & 2)  && ! (gpte & _PAGE_RW) )
  26.370 +    {
  26.371 +	    // write fault on RO page
  26.372 +	    return 0;
  26.373 +	}
  26.374 +
  26.375 +    spin_lock(&current->mm.shadow_lock);
  26.376 +    // take the lock and reread gpte
  26.377 +
  26.378 +	if ( unlikely(__get_user(gpte, (unsigned long*)&linear_pg_table[va>>PAGE_SHIFT])) )
  26.379 +	{
  26.380 +		SH_VVLOG("shadow_fault - EXIT: read gpte faulted" );
  26.381 +		spin_unlock(&current->mm.shadow_lock);
  26.382 +		return 0;  // propagate to guest
  26.383 +	}
  26.384 +
  26.385 +	if ( unlikely(!(gpte & _PAGE_PRESENT)) )
  26.386 +	{
  26.387 +		SH_VVLOG("shadow_fault - EXIT: gpte not present (%lx)",gpte );
  26.388 +		spin_unlock(&current->mm.shadow_lock);
  26.389 +		return 0;  // we're not going to be able to help
  26.390 +    }
  26.391 +
  26.392 +    spte = gpte;
  26.393 +
  26.394 +	if ( error_code & 2  )  
  26.395 +	{  // write fault
  26.396 +		if ( likely(gpte & _PAGE_RW) )
  26.397 +	    {
  26.398 +			gpte |= _PAGE_DIRTY | _PAGE_ACCESSED;
  26.399 +			spte |= _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED; 
  26.400 +            // (we're about to dirty it anyhow...)
  26.401 +		}
  26.402 +		else
  26.403 +		{   // write fault on RO page
  26.404 +            SH_VVLOG("shadow_fault - EXIT: write fault on RO page (%lx)",gpte );
  26.405 +            spin_unlock(&current->mm.shadow_lock);
  26.406 +			return 0; // propagate to guest
  26.407 +			// not clear whether we should set accessed bit here...
  26.408 +		}
  26.409 +	}
  26.410 +	else
  26.411 +	{
  26.412 +		gpte |= _PAGE_ACCESSED;
  26.413 +        spte |= _PAGE_ACCESSED; // about to happen anyway
  26.414 +		if ( ! (gpte & _PAGE_DIRTY) ) 
  26.415 +			spte &= ~_PAGE_RW;  // force clear unless already dirty
  26.416 +	}
  26.417 +
  26.418 + 	SH_VVLOG("plan: gpte=%08lx  spte=%08lx", gpte, spte );
  26.419 +
  26.420 +	// write back updated gpte
  26.421 +    // XXX watch out for read-only L2 entries! (not used in Linux)
  26.422 +	if ( unlikely( __put_user( gpte, (unsigned long*)&linear_pg_table[va>>PAGE_SHIFT])) )
  26.423 +		BUG();  // fixme!
  26.424 +
  26.425 +    if ( unlikely( __put_user( spte, (unsigned long*)&shadow_linear_pg_table[va>>PAGE_SHIFT])) )
  26.426 +	{ 
  26.427 +		// failed:
  26.428 +        //  the L1 may not be shadowed, or the L2 entry may be insufficient
  26.429 +
  26.430 +		unsigned long gpde, spde, gl1pfn, sl1pfn;
  26.431 +
  26.432 +        SH_VVLOG("3: not shadowed or l2 insufficient gpte=%08lx  spte=%08lx",gpte,spte );
  26.433 +
  26.434 +        gpde = l2_pgentry_val(linear_l2_table[va>>L2_PAGETABLE_SHIFT]);
  26.435 +
  26.436 +        gl1pfn = gpde>>PAGE_SHIFT;
  26.437 +
  26.438 +        
  26.439 +        if ( ! (sl1pfn=__shadow_status(current, gl1pfn) ) )
  26.440 +        {
  26.441 +            // this L1 is NOT already shadowed so we need to shadow it
  26.442 +            struct pfn_info *sl1pfn_info;
  26.443 +            unsigned long *gpl1e, *spl1e;
  26.444 +            int i;
  26.445 +            sl1pfn_info = alloc_domain_page( NULL ); // XXX account properly! 
  26.446 +            sl1pfn = sl1pfn_info - frame_table;
  26.447 +
  26.448 +            SH_VVLOG("4a: l1 not shadowed ( %08lx )",sl1pfn);
  26.449 +	        perfc_incrc(shadow_l1_table_count);
  26.450 +	        perfc_incr(shadow_l1_pages);
  26.451 +
  26.452 +            set_shadow_status(current, gl1pfn, PSH_shadowed | sl1pfn);
  26.453 +
  26.454 +            gpde = gpde | _PAGE_ACCESSED | _PAGE_DIRTY;
  26.455 +            spde = (gpde & ~PAGE_MASK) | _PAGE_RW | (sl1pfn<<PAGE_SHIFT);
  26.456 +        
  26.457 +
  26.458 +            linear_l2_table[va>>L2_PAGETABLE_SHIFT] = mk_l2_pgentry(gpde);
  26.459 +            shadow_linear_l2_table[va>>L2_PAGETABLE_SHIFT] =  mk_l2_pgentry(spde);
  26.460 +
  26.461 +            gpl1e = (unsigned long *) &(linear_pg_table[
  26.462 +                         (va>>PAGE_SHIFT) & ~(ENTRIES_PER_L1_PAGETABLE-1) ]);
  26.463 +
  26.464 +            spl1e = (unsigned long *) &shadow_linear_pg_table[
  26.465 +                         (va>>PAGE_SHIFT) & ~(ENTRIES_PER_L1_PAGETABLE-1) ];
  26.466 +
  26.467 +
  26.468 +			// XXX can only do this is the shadow/guest is writeable
  26.469 +            // disable write protection if ! gpde & _PAGE_RW ????
  26.470 +
  26.471 +            for ( i = 0; i < ENTRIES_PER_L1_PAGETABLE; i++ )
  26.472 +	        {
  26.473 +#if SHADOW_OPTIMISE
  26.474 +                if ( (gpl1e[i] & (_PAGE_PRESENT|_PAGE_ACCESSED) ) == 
  26.475 +                                (_PAGE_PRESENT|_PAGE_ACCESSED) )
  26.476 +                {
  26.477 +                    spl1e[i] = gpl1e[i];
  26.478 +                    if ( !(gpl1e[i] & _PAGE_DIRTY) )
  26.479 +                        spl1e[i] &= ~_PAGE_RW;
  26.480 +                }
  26.481 +                else
  26.482 +#endif
  26.483 +                    spl1e[i] = 0;
  26.484 +            }
  26.485 +
  26.486 +
  26.487 +        }
  26.488 +        else
  26.489 +        {
  26.490 +            // this L1 was shadowed (by another PT) but we didn't have an L2
  26.491 +            // entry for it
  26.492 +
  26.493 +            SH_VVLOG("4b: was shadowed, l2 missing ( %08lx )",sl1pfn);
  26.494 +
  26.495 +		    spde = (gpde & ~PAGE_MASK) | (sl1pfn<<PAGE_SHIFT) | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY;
  26.496 +
  26.497 +            gpde = gpde | _PAGE_ACCESSED | _PAGE_DIRTY;
  26.498 +
  26.499 +
  26.500 +			if ( unlikely( (sl1pfn<<PAGE_SHIFT) == (gl1pfn<<PAGE_SHIFT)  ) )
  26.501 +			{   // detect linear map, and keep pointing at guest
  26.502 +                SH_VLOG("4c: linear mapping ( %08lx )",sl1pfn);
  26.503 +				spde = (spde & ~PAGE_MASK) | (gl1pfn<<PAGE_SHIFT);
  26.504 +			}
  26.505 +
  26.506 +            linear_l2_table[va>>L2_PAGETABLE_SHIFT] = mk_l2_pgentry(gpde);
  26.507 +            shadow_linear_l2_table[va>>L2_PAGETABLE_SHIFT] = mk_l2_pgentry(spde);
  26.508 +			
  26.509 +
  26.510 +        }              
  26.511 +
  26.512 +        shadow_linear_pg_table[va>>PAGE_SHIFT] = mk_l1_pgentry(spte);
  26.513 +        // (we need to do the above even if we've just made the shadow L1)
  26.514 +
  26.515 +    } // end of fixup writing the shadow L1 directly failed
  26.516 +    	
  26.517 +    perfc_incrc(shadow_fixup_count);
  26.518 +
  26.519 +    check_pagetable( current, current->mm.pagetable, "post-sf" );
  26.520 +
  26.521 +    spin_unlock(&current->mm.shadow_lock);
  26.522 +
  26.523 +    return 1; // let's try the faulting instruction again...
  26.524 +
  26.525 +}
  26.526 +
  26.527 +
  26.528 +void shadow_l1_normal_pt_update( unsigned long pa, unsigned long gpte,
  26.529 +                                 unsigned long *prev_spfn_ptr,
  26.530 +				 l1_pgentry_t **prev_spl1e_ptr )
  26.531 +{
  26.532 +    unsigned long gpfn, spfn, spte, prev_spfn = *prev_spfn_ptr;    
  26.533 +    l1_pgentry_t * spl1e, * prev_spl1e = *prev_spl1e_ptr;
  26.534 +
  26.535 +
  26.536 +SH_VVLOG("shadow_l1_normal_pt_update pa=%08lx, gpte=%08lx, prev_spfn=%08lx, prev_spl1e=%08lx\n",
  26.537 +pa,gpte,prev_spfn, prev_spl1e);
  26.538 +
  26.539 +    // to get here, we know the l1 page *must* be shadowed
  26.540 +
  26.541 +    gpfn = pa >> PAGE_SHIFT;
  26.542 +    spfn = __shadow_status(current, gpfn) & PSH_pfn_mask;
  26.543 +
  26.544 +    if ( spfn == prev_spfn )
  26.545 +    {
  26.546 +        spl1e = prev_spl1e;
  26.547 +    }
  26.548 +    else
  26.549 +    {
  26.550 +        if( prev_spl1e ) unmap_domain_mem( prev_spl1e );
  26.551 +        spl1e = (l1_pgentry_t *) map_domain_mem( spfn << PAGE_SHIFT );
  26.552 +	    *prev_spfn_ptr  = spfn;
  26.553 +	    *prev_spl1e_ptr = spl1e;
  26.554 +    }
  26.555 +	// XXX we assume only pagetables can be shadowed; this will have to change
  26.556 +	// to allow arbitrary CoW etc.
  26.557 +
  26.558 +    spte = 0;
  26.559 +
  26.560 +#if SHADOW_OPTIMISE
  26.561 +	if ( (gpte & (_PAGE_PRESENT|_PAGE_ACCESSED) ) == 
  26.562 +		 (_PAGE_PRESENT|_PAGE_ACCESSED) )
  26.563 +    {
  26.564 +        spte = gpte;
  26.565 +		if ( !(gpte & _PAGE_DIRTY ) )
  26.566 +			gpte &= ~ _PAGE_RW;
  26.567 +	}
  26.568 +#endif
  26.569 +
  26.570 +	spl1e[(pa & ~PAGE_MASK) / sizeof(l1_pgentry_t) ] = 
  26.571 +		mk_l1_pgentry( spte );
  26.572 +
  26.573 +	//unmap_domain_mem( (void *) spl1e );
  26.574 +}
  26.575 +
  26.576 +void shadow_l2_normal_pt_update( unsigned long pa, unsigned long gpte )
  26.577 +{
  26.578 +    unsigned long gpfn, spfn, spte;
  26.579 +    l2_pgentry_t * sp2le;
  26.580 +    unsigned long s_sh=0;
  26.581 +
  26.582 +    SH_VVLOG("shadow_l2_normal_pt_update pa=%08lx, gpte=%08lx",pa,gpte);
  26.583 +
  26.584 +    // to get here, we know the l2 page has a shadow
  26.585 +
  26.586 +    gpfn = pa >> PAGE_SHIFT;
  26.587 +    spfn = __shadow_status(current, gpfn) & PSH_pfn_mask;
  26.588 +
  26.589 +
  26.590 +    spte = 0;
  26.591 +
  26.592 +	if( gpte & _PAGE_PRESENT )
  26.593 +		s_sh = __shadow_status(current, gpte >> PAGE_SHIFT);
  26.594 +
  26.595 +    sp2le = (l2_pgentry_t *) map_domain_mem( spfn << PAGE_SHIFT );
  26.596 +    // no real need for a cache here
  26.597 +		
  26.598 +	if ( s_sh ) // PSH_shadowed
  26.599 +	{
  26.600 +		if ( unlikely( (frame_table[gpte>>PAGE_SHIFT].type_and_flags & PGT_type_mask) == PGT_l2_page_table) )
  26.601 +		{ 
  26.602 +            // linear page table case
  26.603 +			spte = (gpte & ~_PAGE_RW) | _PAGE_DIRTY | _PAGE_ACCESSED; 
  26.604 +	    }
  26.605 +	    else
  26.606 +			spte = (gpte & ~PAGE_MASK) | (s_sh<<PAGE_SHIFT) | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED;
  26.607 +
  26.608 +	}
  26.609 +
  26.610 +	// XXXX Should mark guest pte as DIRTY and ACCESSED too!!!!!
  26.611 +
  26.612 +	sp2le[(pa & ~PAGE_MASK) / sizeof(l2_pgentry_t) ] = 
  26.613 +		mk_l2_pgentry( spte );
  26.614 +
  26.615 +	unmap_domain_mem( (void *) sp2le );
  26.616 +}
  26.617 +
  26.618 +
  26.619 +#if SHADOW_DEBUG
  26.620 +
  26.621 +static int sh_l2_present;
  26.622 +static int sh_l1_present;
  26.623 +char * sh_check_name;
  26.624 +
  26.625 +#define FAIL(_f, _a...)                             \
  26.626 +{printk("XXX %s-FAIL (%d,%d)" _f " g=%08lx s=%08lx\n",  sh_check_name, level, i, ## _a , gpte, spte ); BUG();}
  26.627 +
  26.628 +static int check_pte( struct task_struct *p, 
  26.629 +			   unsigned long gpte, unsigned long spte, int level, int i )
  26.630 +{
  26.631 +	unsigned long mask, gpfn, spfn;
  26.632 +
  26.633 +    if ( spte == 0 || spte == 0xdeadface || spte == 0x00000E00)
  26.634 +        return 1;  // always safe
  26.635 +
  26.636 +    if ( !(spte & _PAGE_PRESENT) )
  26.637 +        FAIL("Non zero not present spte");
  26.638 +
  26.639 +	if( level == 2 ) sh_l2_present++;
  26.640 +	if( level == 1 ) sh_l1_present++;
  26.641 +
  26.642 +    if ( !(gpte & _PAGE_PRESENT) )
  26.643 +        FAIL("Guest not present yet shadow is");
  26.644 +
  26.645 +    mask = ~(_PAGE_DIRTY|_PAGE_ACCESSED|_PAGE_RW|0xFFFFF000);
  26.646 +
  26.647 +    if ( (spte & mask) != (gpte & mask ) )
  26.648 +		FAIL("Corrupt?");
  26.649 +
  26.650 +	if ( (spte & _PAGE_DIRTY ) && !(gpte & _PAGE_DIRTY) )
  26.651 +		FAIL("Dirty coherence");
  26.652 +
  26.653 +	if ( (spte & _PAGE_ACCESSED ) && !(gpte & _PAGE_ACCESSED) )
  26.654 +		FAIL("Accessed coherence");
  26.655 +
  26.656 +	if ( (spte & _PAGE_RW ) && !(gpte & _PAGE_RW) )
  26.657 +		FAIL("RW coherence");
  26.658 +
  26.659 +	if ( (spte & _PAGE_RW ) && !((gpte & _PAGE_RW) && (gpte & _PAGE_DIRTY) ))
  26.660 +		FAIL("RW2 coherence");
  26.661 +	
  26.662 +	spfn = spte>>PAGE_SHIFT;
  26.663 +	gpfn = gpte>>PAGE_SHIFT;
  26.664 +
  26.665 +	if ( gpfn == spfn )
  26.666 +    {
  26.667 +		if ( level > 1 )
  26.668 +			FAIL("Linear map ???");			 // XXX this will fail on BSD
  26.669 +
  26.670 +		return 1;
  26.671 +	}
  26.672 +	else
  26.673 +	{
  26.674 +		if ( level < 2 )
  26.675 +			FAIL("Shadow in L1 entry?");
  26.676 +
  26.677 +		if ( __shadow_status(p, gpfn) != (PSH_shadowed | spfn) )
  26.678 +			FAIL("spfn problem g.sf=%08lx", 
  26.679 +				 __shadow_status(p, gpfn) );
  26.680 +	}
  26.681 +
  26.682 +	return 1;
  26.683 +}
  26.684 +
  26.685 +
  26.686 +static int check_l1_table( struct task_struct *p, unsigned long va, 
  26.687 +					unsigned long g2, unsigned long s2 )
  26.688 +{
  26.689 +	int j;
  26.690 +	unsigned long *gpl1e, *spl1e;
  26.691 +
  26.692 +	//gpl1e = (unsigned long *) &(linear_pg_table[ va>>PAGE_SHIFT]);
  26.693 +	//spl1e = (unsigned long *) &(shadow_linear_pg_table[ va>>PAGE_SHIFT]);
  26.694 +
  26.695 +	gpl1e = map_domain_mem( g2<<PAGE_SHIFT );
  26.696 +	spl1e = map_domain_mem( s2<<PAGE_SHIFT );
  26.697 +
  26.698 +	for ( j = 0; j < ENTRIES_PER_L1_PAGETABLE; j++ )
  26.699 +	{
  26.700 +		unsigned long gpte = gpl1e[j];
  26.701 +		unsigned long spte = spl1e[j];
  26.702 +		
  26.703 +		check_pte( p, gpte, spte, 1, j );
  26.704 +	}
  26.705 +	
  26.706 +	unmap_domain_mem( spl1e );
  26.707 +	unmap_domain_mem( gpl1e );
  26.708 +
  26.709 +	return 1;
  26.710 +}
  26.711 +
  26.712 +#define FAILPT(_f, _a...)                             \
  26.713 +{printk("XXX FAIL %s-PT" _f "\n", s, ## _a ); BUG();}
  26.714 +
  26.715 +int check_pagetable( struct task_struct *p, pagetable_t pt, char *s )
  26.716 +{
  26.717 +	unsigned long gptbase = pagetable_val(pt);
  26.718 +	unsigned long gpfn, spfn;
  26.719 +	int i;
  26.720 +	l2_pgentry_t *gpl2e, *spl2e;
  26.721 +
  26.722 +	sh_check_name = s;
  26.723 +
  26.724 +    SH_VVLOG("%s-PT Audit",s);
  26.725 +
  26.726 +	sh_l2_present = sh_l1_present = 0;
  26.727 +
  26.728 +	gpfn =  gptbase >> PAGE_SHIFT;
  26.729 +
  26.730 +	if ( ! (__shadow_status(p, gpfn) & PSH_shadowed) )
  26.731 +	{
  26.732 +		printk("%s-PT %08lx not shadowed\n", s, gptbase);
  26.733 +
  26.734 +		if( __shadow_status(p, gpfn) != 0 ) BUG();
  26.735 +
  26.736 +		return 0;
  26.737 +	}
  26.738 +	
  26.739 +    spfn = __shadow_status(p, gpfn) & PSH_pfn_mask;
  26.740 +
  26.741 +	if ( ! __shadow_status(p, gpfn) == (PSH_shadowed | spfn) )
  26.742 +		FAILPT("ptbase shadow inconsistent1");
  26.743 +
  26.744 +	gpl2e = (l2_pgentry_t *) map_domain_mem( gpfn << PAGE_SHIFT );
  26.745 +	spl2e = (l2_pgentry_t *) map_domain_mem( spfn << PAGE_SHIFT );
  26.746 +
  26.747 +	//ipl2e = (l2_pgentry_t *) map_domain_mem( spfn << PAGE_SHIFT );
  26.748 +
  26.749 +
  26.750 +	if ( memcmp( &spl2e[DOMAIN_ENTRIES_PER_L2_PAGETABLE],
  26.751 +			&gpl2e[DOMAIN_ENTRIES_PER_L2_PAGETABLE], 
  26.752 +			((SH_LINEAR_PT_VIRT_START>>(L2_PAGETABLE_SHIFT))-DOMAIN_ENTRIES_PER_L2_PAGETABLE)
  26.753 +			* sizeof(l2_pgentry_t)) )
  26.754 +	{
  26.755 +		printk("gpfn=%08lx spfn=%08lx\n", gpfn, spfn);
  26.756 +		for (i=DOMAIN_ENTRIES_PER_L2_PAGETABLE; 
  26.757 +			 i<(SH_LINEAR_PT_VIRT_START>>(L2_PAGETABLE_SHIFT));
  26.758 +			 i++ )
  26.759 +			printk("+++ (%d) %08lx %08lx\n",i,
  26.760 +				   l2_pgentry_val(gpl2e[i]), l2_pgentry_val(spl2e[i]) );
  26.761 +		FAILPT("hypervisor entries inconsistent");
  26.762 +	}
  26.763 +
  26.764 +	if ( (l2_pgentry_val(spl2e[LINEAR_PT_VIRT_START >> L2_PAGETABLE_SHIFT]) != 
  26.765 +		  l2_pgentry_val(gpl2e[LINEAR_PT_VIRT_START >> L2_PAGETABLE_SHIFT])) )
  26.766 +		FAILPT("hypervisor linear map inconsistent");
  26.767 +
  26.768 +	if ( (l2_pgentry_val(spl2e[SH_LINEAR_PT_VIRT_START >> L2_PAGETABLE_SHIFT]) != 
  26.769 +		  ((spfn << PAGE_SHIFT) | __PAGE_HYPERVISOR)) )
  26.770 +		FAILPT("hypervisor shadow linear map inconsistent %08lx %08lx",
  26.771 +			   l2_pgentry_val(spl2e[SH_LINEAR_PT_VIRT_START >> L2_PAGETABLE_SHIFT]),
  26.772 +			   		  (spfn << PAGE_SHIFT) | __PAGE_HYPERVISOR
  26.773 +			   );
  26.774 +
  26.775 +	if ( (l2_pgentry_val(spl2e[PERDOMAIN_VIRT_START >> L2_PAGETABLE_SHIFT]) !=
  26.776 +		  ((__pa(frame_table[gpfn].u.domain->mm.perdomain_pt) | __PAGE_HYPERVISOR))) )
  26.777 +		FAILPT("hypervisor per-domain map inconsistent");
  26.778 +
  26.779 +
  26.780 +	// check the whole L2
  26.781 +	for ( i = 0; i < DOMAIN_ENTRIES_PER_L2_PAGETABLE; i++ )
  26.782 +	{
  26.783 +		unsigned long gpte = l2_pgentry_val(gpl2e[i]);
  26.784 +		unsigned long spte = l2_pgentry_val(spl2e[i]);
  26.785 +
  26.786 +		check_pte( p, gpte, spte, 2, i );
  26.787 +	}
  26.788 +
  26.789 +
  26.790 +	// go back and recurse
  26.791 +	for ( i = 0; i < DOMAIN_ENTRIES_PER_L2_PAGETABLE; i++ )
  26.792 +	{
  26.793 +		unsigned long gpte = l2_pgentry_val(gpl2e[i]);
  26.794 +		unsigned long spte = l2_pgentry_val(spl2e[i]);
  26.795 +
  26.796 +		if ( spte )	   
  26.797 +			check_l1_table( p,
  26.798 +				i<<L2_PAGETABLE_SHIFT,
  26.799 +				gpte>>PAGE_SHIFT, spte>>PAGE_SHIFT );
  26.800 +
  26.801 +	}
  26.802 +
  26.803 +	unmap_domain_mem( spl2e );
  26.804 +	unmap_domain_mem( gpl2e );
  26.805 +
  26.806 +	SH_VVLOG("PT verified : l2_present = %d, l1_present = %d\n",
  26.807 +		   sh_l2_present, sh_l1_present );
  26.808 +	
  26.809 +	return 1;
  26.810 +}
  26.811 +
  26.812 +
  26.813 +#endif
  26.814 +
  26.815 +
  26.816 +
  26.817 +
  26.818 +
    27.1 --- a/xen/drivers/block/xen_block.c	Wed Mar 24 19:05:53 2004 +0000
    27.2 +++ b/xen/drivers/block/xen_block.c	Thu Mar 25 15:02:26 2004 +0000
    27.3 @@ -539,7 +539,6 @@ static void dispatch_rw_block_io(struct 
    27.4  static void make_response(struct task_struct *p, unsigned long id, 
    27.5  			  unsigned short op, unsigned long st)
    27.6  {
    27.7 -    unsigned long cpu_mask;
    27.8      blk_ring_resp_entry_t *resp;
    27.9  
   27.10      /* Place on the response ring for the relevant domain. */ 
   27.11 @@ -553,8 +552,7 @@ static void make_response(struct task_st
   27.12      spin_unlock(&p->blk_ring_lock);
   27.13      
   27.14      /* Kick the relevant domain. */
   27.15 -    cpu_mask = mark_guest_event(p, _EVENT_BLKDEV);
   27.16 -    guest_event_notify(cpu_mask); 
   27.17 +    send_guest_virq(p, VIRQ_BLKDEV);
   27.18  }
   27.19  
   27.20  static void dump_blockq(u_char key, void *dev_id, struct pt_regs *regs) 
    28.1 --- a/xen/drivers/block/xen_vbd.c	Wed Mar 24 19:05:53 2004 +0000
    28.2 +++ b/xen/drivers/block/xen_vbd.c	Thu Mar 25 15:02:26 2004 +0000
    28.3 @@ -29,7 +29,6 @@ long __vbd_create(struct task_struct *p,
    28.4      vbd_t *vbd; 
    28.5      rb_node_t **rb_p, *rb_parent = NULL;
    28.6      long ret = 0;
    28.7 -    unsigned long cpu_mask;
    28.8  
    28.9      spin_lock(&p->vbd_lock);
   28.10  
   28.11 @@ -69,8 +68,7 @@ long __vbd_create(struct task_struct *p,
   28.12      rb_link_node(&vbd->rb, rb_parent, rb_p);
   28.13      rb_insert_color(&vbd->rb, &p->vbd_rb);
   28.14  
   28.15 -    cpu_mask = mark_guest_event(p, _EVENT_VBD_UPD);
   28.16 -    guest_event_notify(cpu_mask);
   28.17 +    send_guest_virq(p, VIRQ_VBD_UPD);
   28.18  
   28.19   out:
   28.20      spin_unlock(&p->vbd_lock);
   28.21 @@ -110,7 +108,6 @@ long __vbd_grow(struct task_struct *p,
   28.22      vbd_t *vbd = NULL;
   28.23      rb_node_t *rb;
   28.24      long ret = 0;
   28.25 -    unsigned long cpu_mask;
   28.26  
   28.27      spin_lock(&p->vbd_lock);
   28.28  
   28.29 @@ -150,8 +147,7 @@ long __vbd_grow(struct task_struct *p,
   28.30  
   28.31      *px = x;
   28.32  
   28.33 -    cpu_mask = mark_guest_event(p, _EVENT_VBD_UPD);
   28.34 -    guest_event_notify(cpu_mask);
   28.35 +    send_guest_virq(p, VIRQ_VBD_UPD);
   28.36  
   28.37   out:
   28.38      spin_unlock(&p->vbd_lock);
   28.39 @@ -190,7 +186,6 @@ long vbd_shrink(vbd_shrink_t *shrink)
   28.40      vbd_t *vbd = NULL;
   28.41      rb_node_t *rb;
   28.42      long ret = 0;
   28.43 -    unsigned long cpu_mask;
   28.44  
   28.45      if ( !IS_PRIV(current) )
   28.46          return -EPERM; 
   28.47 @@ -233,8 +228,7 @@ long vbd_shrink(vbd_shrink_t *shrink)
   28.48      *px = x->next;
   28.49      kfree(x);
   28.50  
   28.51 -    cpu_mask = mark_guest_event(p, _EVENT_VBD_UPD);
   28.52 -    guest_event_notify(cpu_mask);
   28.53 +    send_guest_virq(p, VIRQ_VBD_UPD);
   28.54  
   28.55   out:
   28.56      spin_unlock(&p->vbd_lock);
   28.57 @@ -252,7 +246,6 @@ long vbd_setextents(vbd_setextents_t *se
   28.58      rb_node_t *rb;
   28.59      int i;
   28.60      long ret = 0;
   28.61 -    unsigned long cpu_mask;
   28.62  
   28.63      if ( !IS_PRIV(current) )
   28.64          return -EPERM; 
   28.65 @@ -323,8 +316,7 @@ long vbd_setextents(vbd_setextents_t *se
   28.66      /* Make the new list visible. */
   28.67      vbd->extents = new_extents;
   28.68  
   28.69 -    cpu_mask = mark_guest_event(p, _EVENT_VBD_UPD);
   28.70 -    guest_event_notify(cpu_mask);
   28.71 +    send_guest_virq(p, VIRQ_VBD_UPD);
   28.72  
   28.73   out:
   28.74      spin_unlock(&p->vbd_lock);
   28.75 @@ -348,7 +340,6 @@ long vbd_delete(vbd_delete_t *delete)
   28.76      vbd_t *vbd;
   28.77      rb_node_t *rb;
   28.78      xen_extent_le_t *x, *t;
   28.79 -    unsigned long cpu_mask;
   28.80  
   28.81      if( !IS_PRIV(current) )
   28.82          return -EPERM; 
   28.83 @@ -392,8 +383,7 @@ long vbd_delete(vbd_delete_t *delete)
   28.84          x = t;
   28.85      }
   28.86      
   28.87 -    cpu_mask = mark_guest_event(p, _EVENT_VBD_UPD);
   28.88 -    guest_event_notify(cpu_mask);
   28.89 +    send_guest_virq(p, VIRQ_VBD_UPD);
   28.90     
   28.91      spin_unlock(&p->vbd_lock);
   28.92      put_task_struct(p);
   28.93 @@ -406,7 +396,6 @@ void destroy_all_vbds(struct task_struct
   28.94      vbd_t *vbd;
   28.95      rb_node_t *rb;
   28.96      xen_extent_le_t *x, *t;
   28.97 -    unsigned long cpu_mask;
   28.98  
   28.99      spin_lock(&p->vbd_lock);
  28.100  
  28.101 @@ -426,8 +415,7 @@ void destroy_all_vbds(struct task_struct
  28.102          }          
  28.103      }
  28.104  
  28.105 -    cpu_mask = mark_guest_event(p, _EVENT_VBD_UPD);
  28.106 -    guest_event_notify(cpu_mask);
  28.107 +    send_guest_virq(p, VIRQ_VBD_UPD);
  28.108  
  28.109      spin_unlock(&p->vbd_lock);
  28.110  }
    29.1 --- a/xen/drivers/char/console.c	Wed Mar 24 19:05:53 2004 +0000
    29.2 +++ b/xen/drivers/char/console.c	Thu Mar 25 15:02:26 2004 +0000
    29.3 @@ -243,7 +243,6 @@ static void switch_serial_input(void)
    29.4  static void __serial_rx(unsigned char c, struct pt_regs *regs)
    29.5  {
    29.6      key_handler *handler;
    29.7 -    unsigned long cpu_mask;
    29.8      struct task_struct *p;
    29.9  
   29.10      if ( xen_rx )
   29.11 @@ -257,8 +256,7 @@ static void __serial_rx(unsigned char c,
   29.12          if ( serial_rx_prod++ == serial_rx_cons )
   29.13          {
   29.14              p = find_domain_by_id(0); /* only DOM0 reads the serial buffer */
   29.15 -            cpu_mask = mark_guest_event(p, _EVENT_CONSOLE);
   29.16 -            guest_event_notify(cpu_mask);
   29.17 +            send_guest_virq(p, VIRQ_CONSOLE);
   29.18              put_task_struct(p);
   29.19          }
   29.20      }
    30.1 --- a/xen/drivers/char/keyboard.c	Wed Mar 24 19:05:53 2004 +0000
    30.2 +++ b/xen/drivers/char/keyboard.c	Thu Mar 25 15:02:26 2004 +0000
    30.3 @@ -193,7 +193,7 @@ static void keyboard_interrupt(int irq, 
    30.4  {
    30.5      unsigned char status=0, scancode;
    30.6      unsigned int work = 1000;
    30.7 -    unsigned long cpu_mask = 0, flags;
    30.8 +    unsigned long flags;
    30.9      struct task_struct *p = CONSOLE_OWNER;
   30.10  
   30.11      spin_lock_irqsave(&kbd_lock, flags);
   30.12 @@ -227,7 +227,7 @@ static void keyboard_interrupt(int irq, 
   30.13          if ( p != NULL )
   30.14          {
   30.15              kbd_ring_push(status, scancode);
   30.16 -            cpu_mask |= mark_guest_event(p, _EVENT_PS2);
   30.17 +            send_guest_virq(p, VIRQ_PS2);
   30.18          }
   30.19      }
   30.20      
   30.21 @@ -237,10 +237,7 @@ static void keyboard_interrupt(int irq, 
   30.22      spin_unlock_irqrestore(&kbd_lock, flags);
   30.23  
   30.24      if ( p != NULL )
   30.25 -    {
   30.26          put_task_struct(p);
   30.27 -        guest_event_notify(cpu_mask);
   30.28 -    }
   30.29  }
   30.30      
   30.31      
    31.1 --- a/xen/include/asm-i386/config.h	Wed Mar 24 19:05:53 2004 +0000
    31.2 +++ b/xen/include/asm-i386/config.h	Thu Mar 25 15:02:26 2004 +0000
    31.3 @@ -40,6 +40,7 @@
    31.4  
    31.5  #define CONFIG_XEN_ATTENTION_KEY 1
    31.6  
    31.7 +
    31.8  #define HZ 100
    31.9  
   31.10  /*
   31.11 @@ -68,7 +69,7 @@
   31.12   */
   31.13  #define MAX_MONITOR_ADDRESS   (16*1024*1024)
   31.14  #define MAX_DMA_ADDRESS       (16*1024*1024)
   31.15 -#define MAX_DIRECTMAP_ADDRESS (44*1024*1024)
   31.16 +#define MAX_DIRECTMAP_ADDRESS (40*1024*1024) // XXX was 44
   31.17  /* And the virtual addresses for the direct-map region... */
   31.18  #define DIRECTMAP_VIRT_START  (READONLY_MPT_VIRT_END)
   31.19  #define DIRECTMAP_VIRT_END    (DIRECTMAP_VIRT_START + MAX_DIRECTMAP_ADDRESS)
   31.20 @@ -81,8 +82,11 @@
   31.21  /* Next 4MB of virtual address space is used as a linear p.t. mapping. */
   31.22  #define LINEAR_PT_VIRT_START  (DIRECTMAP_VIRT_END)
   31.23  #define LINEAR_PT_VIRT_END    (LINEAR_PT_VIRT_START + (4*1024*1024))
   31.24 +/* Next 4MB of virtual address space is used as a shadow linear p.t. map. */
   31.25 +#define SH_LINEAR_PT_VIRT_START  (LINEAR_PT_VIRT_END)
   31.26 +#define SH_LINEAR_PT_VIRT_END    (SH_LINEAR_PT_VIRT_START + (4*1024*1024))
   31.27  /* Next 4MB of virtual address space used for per-domain mappings (eg. GDT). */
   31.28 -#define PERDOMAIN_VIRT_START  (LINEAR_PT_VIRT_END)
   31.29 +#define PERDOMAIN_VIRT_START  (SH_LINEAR_PT_VIRT_END)
   31.30  #define PERDOMAIN_VIRT_END    (PERDOMAIN_VIRT_START + (4*1024*1024))
   31.31  #define GDT_VIRT_START        (PERDOMAIN_VIRT_START)
   31.32  #define GDT_VIRT_END          (GDT_VIRT_START + (64*1024))
    32.1 --- a/xen/include/asm-i386/page.h	Wed Mar 24 19:05:53 2004 +0000
    32.2 +++ b/xen/include/asm-i386/page.h	Thu Mar 25 15:02:26 2004 +0000
    32.3 @@ -91,6 +91,7 @@ typedef struct { unsigned long pt_lo; } 
    32.4  #include <asm/flushtlb.h>
    32.5  
    32.6  #define linear_pg_table ((l1_pgentry_t *)LINEAR_PT_VIRT_START)
    32.7 +#define linear_l2_table ((l2_pgentry_t *)(LINEAR_PT_VIRT_START+(LINEAR_PT_VIRT_START>>(L2_PAGETABLE_SHIFT-L1_PAGETABLE_SHIFT))))
    32.8  
    32.9  extern l2_pgentry_t idle_pg_table[ENTRIES_PER_L2_PAGETABLE];
   32.10  extern void paging_init(void);
    33.1 --- a/xen/include/asm-i386/processor.h	Wed Mar 24 19:05:53 2004 +0000
    33.2 +++ b/xen/include/asm-i386/processor.h	Thu Mar 25 15:02:26 2004 +0000
    33.3 @@ -12,6 +12,7 @@
    33.4  #include <asm/cpufeature.h>
    33.5  #include <asm/desc.h>
    33.6  #include <xen/config.h>
    33.7 +#include <xen/spinlock.h>
    33.8  #include <hypervisor-ifs/hypervisor-if.h>
    33.9  
   33.10  struct task_struct;
   33.11 @@ -415,6 +416,16 @@ struct mm_struct {
   33.12       */
   33.13      l1_pgentry_t *perdomain_pt;
   33.14      pagetable_t  pagetable;
   33.15 +
   33.16 +    unsigned int shadow_mode;  /* flags to control shadow table operation */
   33.17 +    pagetable_t  shadow_table;
   33.18 +    spinlock_t shadow_lock;
   33.19 +    struct shadow_status *shadow_ht;
   33.20 +    struct shadow_status *shadow_ht_free;
   33.21 +    struct shadow_status *shadow_ht_extras; // extra allocation units
   33.22 +    unsigned int shadow_page_count;
   33.23 +    unsigned int shadow_max_page_count;
   33.24 +
   33.25      /* Current LDT details. */
   33.26      unsigned long ldt_base, ldt_ents, shadow_ldt_mapcnt;
   33.27      /* Next entry is passed to LGDT on domain switch. */
    34.1 --- a/xen/include/hypervisor-ifs/dom0_ops.h	Wed Mar 24 19:05:53 2004 +0000
    34.2 +++ b/xen/include/hypervisor-ifs/dom0_ops.h	Thu Mar 25 15:02:26 2004 +0000
    34.3 @@ -214,6 +214,22 @@ typedef struct dom0_pcidev_access_st
    34.4      int          enable;
    34.5  } dom0_pcidev_access_t;
    34.6  
    34.7 +/* 
    34.8 + * Control shadow pagetables operation
    34.9 + */
   34.10 +#define DOM0_SHADOW_CONTROL   24
   34.11 +
   34.12 +#define DOM0_SHADOW_CONTROL_OP_OFF         0
   34.13 +#define DOM0_SHADOW_CONTROL_OP_ENABLE_TEST 1
   34.14 +#define DOM0_SHADOW_CONTROL_OP_FLUSH       10
   34.15 +typedef struct dom0_shadow_control_st
   34.16 +{
   34.17 +    /* IN variables. */
   34.18 +    domid_t      domain;
   34.19 +    int          op;
   34.20 +} dom0_shadow_control_t;
   34.21 +
   34.22 +
   34.23  typedef struct dom0_op_st
   34.24  {
   34.25      unsigned long cmd;
   34.26 @@ -239,6 +255,7 @@ typedef struct dom0_op_st
   34.27          dom0_gettbufs_t         gettbufs;
   34.28          dom0_physinfo_t         physinfo;
   34.29          dom0_pcidev_access_t    pcidev_access;
   34.30 +	dom0_shadow_control_t   shadow_control;
   34.31      } u;
   34.32  } dom0_op_t;
   34.33  
    35.1 --- a/xen/include/hypervisor-ifs/event_channel.h	Wed Mar 24 19:05:53 2004 +0000
    35.2 +++ b/xen/include/hypervisor-ifs/event_channel.h	Thu Mar 25 15:02:26 2004 +0000
    35.3 @@ -10,20 +10,34 @@
    35.4  #define __HYPERVISOR_IFS__EVENT_CHANNEL_H__
    35.5  
    35.6  /*
    35.7 - * EVTCHNOP_open: Open a communication channel between <dom1> and <dom2>.
    35.8 + * EVTCHNOP_bind_interdomain: Open an event channel between <dom1> and <dom2>.
    35.9   * NOTES:
   35.10   *  1. <dom1> and/or <dom2> may be specified as DOMID_SELF.
   35.11   *  2. Only a sufficiently-privileged domain may create an event channel.
   35.12   *  3. <port1> and <port2> are only supplied if the op succeeds.
   35.13   */
   35.14 -#define EVTCHNOP_open           0
   35.15 -typedef struct evtchn_open
   35.16 +#define EVTCHNOP_bind_interdomain 0
   35.17 +typedef struct evtchn_bind_interdomain
   35.18  {
   35.19      /* IN parameters. */
   35.20      domid_t dom1, dom2;
   35.21      /* OUT parameters. */
   35.22      int     port1, port2;
   35.23 -} evtchn_open_t;
   35.24 +} evtchn_bind_interdomain_t;
   35.25 +
   35.26 +/*
   35.27 + * EVTCHNOP_bind_virq: Bind a local event channel to IRQ <irq>.
   35.28 + * NOTES:
   35.29 + *  1. A virtual IRQ may be bound to at most one event channel per domain.
   35.30 + */
   35.31 +#define EVTCHNOP_bind_virq    1
   35.32 +typedef struct evtchn_bind_virq
   35.33 +{
   35.34 +    /* IN parameters. */
   35.35 +    int virq;
   35.36 +    /* OUT parameters. */
   35.37 +    int port;
   35.38 +} evtchn_bind_virq_t;
   35.39  
   35.40  /*
   35.41   * EVTCHNOP_close: Close the communication channel which has an endpoint at
   35.42 @@ -33,7 +47,7 @@ typedef struct evtchn_open
   35.43   *  2. Only a sufficiently-privileged domain may close an event channel
   35.44   *     for which <dom> is not DOMID_SELF.
   35.45   */
   35.46 -#define EVTCHNOP_close          1
   35.47 +#define EVTCHNOP_close            2
   35.48  typedef struct evtchn_close
   35.49  {
   35.50      /* IN parameters. */
   35.51 @@ -46,7 +60,7 @@ typedef struct evtchn_close
   35.52   * EVTCHNOP_send: Send an event to the remote end of the channel whose local
   35.53   * endpoint is <DOMID_SELF, local_port>.
   35.54   */
   35.55 -#define EVTCHNOP_send           2
   35.56 +#define EVTCHNOP_send             3
   35.57  typedef struct evtchn_send
   35.58  {
   35.59      /* IN parameters. */
   35.60 @@ -56,36 +70,45 @@ typedef struct evtchn_send
   35.61  
   35.62  /*
   35.63   * EVTCHNOP_status: Get the current status of the communication channel which
   35.64 - * has an endpoint at <dom1, port1>.
   35.65 + * has an endpoint at <dom, port>.
   35.66   * NOTES:
   35.67 - *  1. <dom1> may be specified as DOMID_SELF.
   35.68 + *  1. <dom> may be specified as DOMID_SELF.
   35.69   *  2. Only a sufficiently-privileged domain may obtain the status of an event
   35.70 - *     channel for which <dom1> is not DOMID_SELF.
   35.71 - *  3. <dom2, port2> is only supplied if status is 'connected'.
   35.72 + *     channel for which <dom> is not DOMID_SELF.
   35.73   */
   35.74 -#define EVTCHNOP_status         3  /* Get status of <channel id>.         */
   35.75 +#define EVTCHNOP_status           4
   35.76  typedef struct evtchn_status
   35.77  {
   35.78      /* IN parameters */
   35.79 -    domid_t dom1;
   35.80 -    int     port1;
   35.81 +    domid_t dom;
   35.82 +    int     port;
   35.83      /* OUT parameters */
   35.84 -    domid_t dom2;
   35.85 -    int     port2;
   35.86 -#define EVTCHNSTAT_closed       0  /* Chennel is not in use.              */
   35.87 -#define EVTCHNSTAT_disconnected 1  /* Channel is not connected to remote. */
   35.88 -#define EVTCHNSTAT_connected    2  /* Channel is connected to remote.     */
   35.89 +#define EVTCHNSTAT_closed       0  /* Chennel is not in use.                 */
   35.90 +#define EVTCHNSTAT_unbound      1  /* Channel is not bound to a source.      */
   35.91 +#define EVTCHNSTAT_interdomain  2  /* Channel is connected to remote domain. */
   35.92 +#define EVTCHNSTAT_pirq     3      /* Channel is bound to a phys IRQ line.   */
   35.93 +#define EVTCHNSTAT_virq     4      /* Channel is bound to a virtual IRQ line */
   35.94      int     status;
   35.95 +    union {
   35.96 +        int __none;    /* EVTCHNSTAT_closed, EVTCHNSTAT_unbound */
   35.97 +        struct {
   35.98 +            domid_t dom;
   35.99 +            int     port;
  35.100 +        } interdomain; /* EVTCHNSTAT_interdomain */
  35.101 +        int pirq;      /* EVTCHNSTAT_pirq        */
  35.102 +        int virq;      /* EVTCHNSTAT_virq        */
  35.103 +    } u;
  35.104  } evtchn_status_t;
  35.105  
  35.106  typedef struct evtchn_op
  35.107  {
  35.108      int cmd; /* EVTCHNOP_* */
  35.109      union {
  35.110 -        evtchn_open_t   open;
  35.111 -        evtchn_close_t  close;
  35.112 -        evtchn_send_t   send;
  35.113 -        evtchn_status_t status;
  35.114 +        evtchn_bind_interdomain_t bind_interdomain;
  35.115 +        evtchn_bind_virq_t        bind_virq;
  35.116 +        evtchn_close_t            close;
  35.117 +        evtchn_send_t             send;
  35.118 +        evtchn_status_t           status;
  35.119      } u;
  35.120  } evtchn_op_t;
  35.121  
    36.1 --- a/xen/include/hypervisor-ifs/hypervisor-if.h	Wed Mar 24 19:05:53 2004 +0000
    36.2 +++ b/xen/include/hypervisor-ifs/hypervisor-if.h	Thu Mar 25 15:02:26 2004 +0000
    36.3 @@ -50,40 +50,25 @@
    36.4  #define ARGS_PER_MULTICALL_ENTRY 8
    36.5  
    36.6  
    36.7 -/* EVENT MESSAGES
    36.8 - *
    36.9 - * Here, as in the interrupts to the guestos, additional network interfaces
   36.10 - * are defined.	 These definitions server as placeholders for the event bits,
   36.11 - * however, in the code these events will allways be referred to as shifted
   36.12 - * offsets from the base NET events.
   36.13 +/* 
   36.14 + * VIRTUAL INTERRUPTS
   36.15 + * 
   36.16 + * Virtual interrupts that a guest OS may receive from the hypervisor.
   36.17   */
   36.18  
   36.19 -/* Events that a guest OS may receive from the hypervisor. */
   36.20 -#define EVENT_BLKDEV   0x01  /* A block device response has been queued. */
   36.21 -#define EVENT_TIMER    0x02  /* A timeout has been updated. */
   36.22 -#define EVENT_DIE      0x04  /* OS is about to be killed. Clean up please! */
   36.23 -#define EVENT_DEBUG    0x08  /* Request guest to dump debug info (gross!) */
   36.24 -#define EVENT_NET      0x10  /* There are packets for transmission. */
   36.25 -#define EVENT_PS2      0x20  /* PS/2 keyboard or mouse event(s) */
   36.26 -#define EVENT_STOP     0x40  /* Prepare for stopping and possible pickling */
   36.27 -#define EVENT_EVTCHN   0x80  /* Event pending on an event channel */
   36.28 -#define EVENT_VBD_UPD  0x100 /* Event to signal VBDs should be reprobed */
   36.29 -#define EVENT_CONSOLE  0x200 /* This is only for domain-0 initial console. */
   36.30 -#define EVENT_PHYSIRQ  0x400 /* Event to signal pending physical IRQs. */
   36.31 -
   36.32 -/* Bit offsets, as opposed to the above masks. */
   36.33 -#define _EVENT_BLKDEV    0
   36.34 -#define _EVENT_TIMER     1
   36.35 -#define _EVENT_DIE       2
   36.36 -#define _EVENT_DEBUG     3
   36.37 -#define _EVENT_NET       4
   36.38 -#define _EVENT_PS2       5
   36.39 -#define _EVENT_STOP      6
   36.40 -#define _EVENT_EVTCHN    7
   36.41 -#define _EVENT_VBD_UPD   8
   36.42 -#define _EVENT_CONSOLE   9
   36.43 -#define _EVENT_PHYSIRQ  10
   36.44 -
   36.45 +#define VIRQ_BLKDEV    0  /* A block device response has been queued. */
   36.46 +#define VIRQ_TIMER     1  /* A timeout has been updated. */
   36.47 +#define VIRQ_DIE       2  /* OS is about to be killed. Clean up please! */
   36.48 +#define VIRQ_DEBUG     3  /* Request guest to dump debug info (gross!) */
   36.49 +#define VIRQ_NET       4  /* There are packets for transmission. */
   36.50 +#define VIRQ_PS2       5  /* PS/2 keyboard or mouse event(s) */
   36.51 +#define VIRQ_STOP      6  /* Prepare for stopping and possible pickling */
   36.52 +#define VIRQ_EVTCHN    7  /* Event pending on an event channel */
   36.53 +#define VIRQ_VBD_UPD   8  /* Event to signal VBDs should be reprobed */
   36.54 +#define VIRQ_CONSOLE   9  /* This is only for domain-0 initial console. */
   36.55 +#define VIRQ_PHYSIRQ  10  /* Event to signal pending physical IRQs. */
   36.56 +#define VIRQ_ERROR    11  /* Catch-all virtual interrupt. */
   36.57 +#define NR_VIRQS      12
   36.58  
   36.59  /*
   36.60   * MMU_XXX: specified in least 2 bits of 'ptr' field. These bits are masked
   36.61 @@ -121,12 +106,6 @@
   36.62  #define UVMF_FLUSH_TLB          1 /* Flush entire TLB. */
   36.63  #define UVMF_INVLPG             2 /* Flush the VA mapping being updated. */
   36.64  
   36.65 -/*
   36.66 - * Master "switch" for enabling/disabling event delivery.
   36.67 - */
   36.68 -#define EVENTS_MASTER_ENABLE_MASK 0x80000000UL
   36.69 -#define EVENTS_MASTER_ENABLE_BIT  31
   36.70 -
   36.71  
   36.72  /*
   36.73   * SCHEDOP_* - Scheduler hypercall operations.
   36.74 @@ -168,49 +147,64 @@ typedef struct
   36.75      unsigned long args[7];
   36.76  } multicall_entry_t;
   36.77  
   36.78 +/* Event channel endpoints per domain. */
   36.79 +#define NR_EVENT_CHANNELS 1024
   36.80 +
   36.81  /*
   36.82   * Xen/guestos shared data -- pointer provided in start_info.
   36.83   * NB. We expect that this struct is smaller than a page.
   36.84   */
   36.85 -typedef struct shared_info_st {
   36.86 -
   36.87 -    /* Bitmask of outstanding event notifications hypervisor -> guest OS. */
   36.88 -    unsigned long events;
   36.89 +typedef struct shared_info_st
   36.90 +{
   36.91      /*
   36.92 -     * Hypervisor will only signal event delivery via the "callback exception"
   36.93 -     * when a pending event is not masked. The mask also contains a "master
   36.94 -     * enable" which prevents any event delivery. This mask can be used to
   36.95 -     * prevent unbounded reentrancy and stack overflow (in this way, acts as a
   36.96 -     * kind of interrupt-enable flag).
   36.97 +     * If bit 0 in evtchn_upcall_pending is transitioned 0->1, and bit 0 in 
   36.98 +     * evtchn_upcall_mask is clear, then an asynchronous upcall is scheduled. 
   36.99 +     * The upcall mask can be used to prevent unbounded reentrancy and stack 
  36.100 +     * overflow (in this way, acts as a kind of interrupt-enable flag).
  36.101       */
  36.102 -    unsigned long events_mask;
  36.103 +    unsigned long evtchn_upcall_pending;
  36.104 +    unsigned long evtchn_upcall_mask;
  36.105  
  36.106      /*
  36.107 -     * A domain can have up to 1024 bidirectional event channels to/from other
  36.108 -     * domains. Domains must agree out-of-band to set up a connection, and then
  36.109 -     * each must explicitly request a connection to the other. When both have
  36.110 -     * made the request the channel is fully allocated and set up.
  36.111 -     * 
  36.112 -     * An event channel is a single sticky 'bit' of information. Setting the
  36.113 -     * sticky bit also causes an upcall into the target domain. In this way
  36.114 -     * events can be seen as an IPI [Inter-Process(or) Interrupt].
  36.115 +     * A domain can have up to 1024 "event channels" on which it can send
  36.116 +     * and receive asynchronous event notifications. There are three classes
  36.117 +     * of event that are delivered by this mechanism:
  36.118 +     *  1. Bi-directional inter- and intra-domain connections. Domains must
  36.119 +     *     arrange out-of-band to set up a connection (usually the setup
  36.120 +     *     is initiated and organised by a privileged third party such as
  36.121 +     *     software running in domain 0).
  36.122 +     *  2. Physical interrupts. A domain with suitable hardware-access
  36.123 +     *     privileges can bind an event-channel port to a physical interrupt
  36.124 +     *     source.
  36.125 +     *  3. Virtual interrupts ('events'). A domain can bind an event-channel
  36.126 +     *     port to a virtual interrupt source, such as the virtual-timer
  36.127 +     *     device or the emergency console.
  36.128       * 
  36.129 -     * A guest can see which of its event channels are pending by reading the
  36.130 -     * 'event_channel_pend' bitfield. To avoid a linear scan of the entire
  36.131 -     * bitfield there is a 'selector' which indicates which words in the
  36.132 -     * bitfield contain at least one set bit.
  36.133 +     * Event channels are addressed by a "port index" between 0 and 1023.
  36.134 +     * Each channel is associated with three bits of information:
  36.135 +     *  1. PENDING -- notifies the domain that there is a pending notification
  36.136 +     *     to be processed. This bit is cleared by the guest.
  36.137 +     *  2. EXCEPTION -- notifies the domain that there has been some
  36.138 +     *     exceptional event associated with this channel (e.g. remote
  36.139 +     *     disconnect, physical IRQ error). This bit is cleared by the guest.
  36.140 +     *  3. MASK -- if this bit is clear then a 0->1 transition of PENDING
  36.141 +     *     or EXCEPTION will cause an asynchronous upcall to be scheduled.
  36.142 +     *     This bit is only updated by the guest. It is read-only within Xen.
  36.143 +     *     If a channel becomes pending or an exceptional event occurs while
  36.144 +     *     the channel is masked then the 'edge' is lost (i.e., when the
  36.145 +     *     channel is unmasked, the guest must manually handle pending
  36.146 +     *     notifications as no upcall will be scheduled by Xen).
  36.147       * 
  36.148 -     * There is a similar bitfield to indicate which event channels have been
  36.149 -     * disconnected by the remote end. There is also a 'selector' for this
  36.150 -     * field.
  36.151 +     * To expedite scanning of pending notifications and exceptions, any 
  36.152 +     * 0->1 transition on an unmasked channel causes a corresponding bit in
  36.153 +     * a 32-bit selector to be set. Each bit in the selector covers a 32-bit
  36.154 +     * word in the PENDING or EXCEPTION bitfield array.
  36.155       */
  36.156 -    u32 event_channel_pend[32];
  36.157 -    u32 event_channel_pend_sel;
  36.158 -    u32 event_channel_disc[32];
  36.159 -    u32 event_channel_disc_sel;
  36.160 -
  36.161 -    /* Bitmask of physical IRQ lines that are pending for this domain. */
  36.162 -    unsigned long physirq_pend;
  36.163 +    u32 evtchn_pending[32];
  36.164 +    u32 evtchn_pending_sel;
  36.165 +    u32 evtchn_exception[32];
  36.166 +    u32 evtchn_exception_sel;
  36.167 +    u32 evtchn_mask[32];
  36.168  
  36.169      /*
  36.170       * Time: The following abstractions are exposed: System Time, Clock Time,
    37.1 --- a/xen/include/xen/event.h	Wed Mar 24 19:05:53 2004 +0000
    37.2 +++ b/xen/include/xen/event.h	Thu Mar 25 15:02:26 2004 +0000
    37.3 @@ -6,33 +6,23 @@
    37.4   * Copyright (c) 2002, K A Fraser
    37.5   */
    37.6  
    37.7 +#ifndef __XEN_EVENT_H__
    37.8 +#define __XEN_EVENT_H__
    37.9 +
   37.10  #include <xen/config.h>
   37.11  #include <xen/sched.h>
   37.12  #include <asm/bitops.h>
   37.13  
   37.14 -#ifdef CONFIG_SMP
   37.15 +/*
   37.16 + * GENERIC SCHEDULING CALLBACK MECHANISMS
   37.17 + */
   37.18  
   37.19 -/*
   37.20 - * mark_guest_event:
   37.21 - *  @p:        Domain to which event should be passed
   37.22 - *  @event:    Event number
   37.23 - *  RETURNS:   "Bitmask" of CPU on which process is currently running
   37.24 - * 
   37.25 - * Idea is that caller may loop on task_list, looking for domains
   37.26 - * to pass events to (using this function). The caller accumulates the
   37.27 - * bits returned by this function (ORing them together) then calls
   37.28 - * event_notify().
   37.29 - * 
   37.30 - * Guest_events are per-domain events passed directly to the guest OS
   37.31 - * in ring 1. 
   37.32 - */
   37.33 -static inline unsigned long mark_guest_event(struct task_struct *p, int event)
   37.34 +/* Schedule an asynchronous callback for the specified domain. */
   37.35 +static inline void __guest_notify(struct task_struct *p)
   37.36  {
   37.37 +#ifdef CONFIG_SMP
   37.38      unsigned long flags, cpu_mask;
   37.39  
   37.40 -    if ( test_and_set_bit(event, &p->shared_info->events) )
   37.41 -        return 0;
   37.42 -
   37.43      spin_lock_irqsave(&schedule_lock[p->processor], flags);
   37.44      if ( p->state == TASK_INTERRUPTIBLE )
   37.45          __wake_up(p);
   37.46 @@ -41,75 +31,85 @@ static inline unsigned long mark_guest_e
   37.47          cpu_mask |= 1 << p->processor;
   37.48      spin_unlock_irqrestore(&schedule_lock[p->processor], flags);
   37.49  
   37.50 -    return cpu_mask;
   37.51 +    cpu_mask &= ~(1 << smp_processor_id());
   37.52 +    if ( cpu_mask != 0 )
   37.53 +        smp_send_event_check_mask(cpu_mask);
   37.54 +#else
   37.55 +    if ( p->state == TASK_INTERRUPTIBLE )
   37.56 +        wake_up(p);
   37.57 +    reschedule(p);
   37.58 +#endif
   37.59  }
   37.60  
   37.61 -/* As above, but hyp_events are handled within the hypervisor. */
   37.62 -static inline unsigned long mark_hyp_event(struct task_struct *p, int event)
   37.63 +static inline void guest_notify(struct task_struct *p)
   37.64  {
   37.65 -    unsigned long flags, cpu_mask;
   37.66 -
   37.67 -    if ( test_and_set_bit(event, &p->hyp_events) )
   37.68 -        return 0;
   37.69 -
   37.70 -    spin_lock_irqsave(&schedule_lock[p->processor], flags);
   37.71 -    if ( p->state == TASK_INTERRUPTIBLE )
   37.72 -        __wake_up(p);
   37.73 -    cpu_mask = __reschedule(p);
   37.74 -    if ( p->has_cpu )
   37.75 -        cpu_mask |= 1 << p->processor;
   37.76 -    spin_unlock_irqrestore(&schedule_lock[p->processor], flags);
   37.77 -
   37.78 -    return cpu_mask;
   37.79 +    /*
   37.80 +     * Upcall already pending or upcalls masked?
   37.81 +     * NB. Suitably synchronised on x86:
   37.82 +     *  We must set the pending bit before checking the mask, but this is
   37.83 +     *  guaranteed to occur because test_and_set_bit() is an ordering barrier.
   37.84 +     */
   37.85 +    if ( !test_and_set_bit(0, &p->shared_info->evtchn_upcall_pending) &&
   37.86 +         !test_bit(0, &p->shared_info->evtchn_upcall_mask) )
   37.87 +        __guest_notify(p);
   37.88  }
   37.89  
   37.90 -/* Notify the given set of CPUs that guest events may be outstanding. */
   37.91 -static inline void guest_event_notify(unsigned long cpu_mask)
   37.92 +
   37.93 +/*
   37.94 + * EVENT-CHANNEL NOTIFICATIONS
   37.95 + * NB. As in guest_notify, evtchn_set_* is suitably synchronised on x86.
   37.96 + */
   37.97 +
   37.98 +static inline void evtchn_set_pending(struct task_struct *p, int port)
   37.99  {
  37.100 -    cpu_mask &= ~(1 << smp_processor_id());
  37.101 -    if ( cpu_mask != 0 ) smp_send_event_check_mask(cpu_mask);
  37.102 +    shared_info_t *s = p->shared_info;
  37.103 +    if ( !test_and_set_bit(port,    &s->evtchn_pending[0]) &&
  37.104 +         !test_bit        (port,    &s->evtchn_mask[0])    &&
  37.105 +         !test_and_set_bit(port>>5, &s->evtchn_pending_sel) )
  37.106 +        guest_notify(p);
  37.107  }
  37.108  
  37.109 -#else
  37.110 -
  37.111 -static inline unsigned long mark_guest_event(struct task_struct *p, int event)
  37.112 +static inline void evtchn_set_exception(struct task_struct *p, int port)
  37.113  {
  37.114 -    if ( !test_and_set_bit(event, &p->shared_info->events) )
  37.115 -    {
  37.116 -        if ( p->state == TASK_INTERRUPTIBLE ) wake_up(p);
  37.117 -        reschedule(p);
  37.118 -    }
  37.119 -    return 0;
  37.120 +    shared_info_t *s = p->shared_info;
  37.121 +    if ( !test_and_set_bit(port,    &s->evtchn_exception[0]) &&
  37.122 +         !test_bit        (port,    &s->evtchn_mask[0])      &&
  37.123 +         !test_and_set_bit(port>>5, &s->evtchn_exception_sel) )
  37.124 +        guest_notify(p);
  37.125  }
  37.126  
  37.127 -static inline unsigned long mark_hyp_event(struct task_struct *p, int event)
  37.128 +/*
  37.129 + * send_guest_virq:
  37.130 + *  @p:        Domain to which virtual IRQ should be sent
  37.131 + *  @virq:     Virtual IRQ number (VIRQ_*)
  37.132 + */
  37.133 +static inline void send_guest_virq(struct task_struct *p, int virq)
  37.134 +{
  37.135 +    evtchn_set_pending(p, p->virq_to_evtchn[virq]);
  37.136 +}
  37.137 +
  37.138 +/*
  37.139 + * send_guest_pirq:
  37.140 + *  @p:        Domain to which physical IRQ should be sent
  37.141 + *  @pirq:     Physical IRQ number
  37.142 + */
  37.143 +static inline void send_guest_pirq(struct task_struct *p, int pirq)
  37.144 +{
  37.145 +    evtchn_set_pending(p, p->pirq_to_evtchn[pirq]);
  37.146 +}
  37.147 +
  37.148 +
  37.149 +/*
  37.150 + * HYPERVISOR-HANDLED EVENTS
  37.151 + */
  37.152 +
  37.153 +static inline void send_hyp_event(struct task_struct *p, int event)
  37.154  {
  37.155      if ( !test_and_set_bit(event, &p->hyp_events) )
  37.156 -    {
  37.157 -        if ( p->state == TASK_INTERRUPTIBLE ) wake_up(p);
  37.158 -        reschedule(p);
  37.159 -    }
  37.160 -    return 0;
  37.161 -}
  37.162 -
  37.163 -#define guest_event_notify(_mask) ((void)0)
  37.164 -
  37.165 -#endif
  37.166 -
  37.167 -/* Notify hypervisor events in thesame way as for guest OS events. */
  37.168 -#define hyp_event_notify(_mask) guest_event_notify(_mask)
  37.169 -
  37.170 -/* Clear a guest-OS event from a per-domain mask. */
  37.171 -static inline void clear_guest_event(struct task_struct *p, int event)
  37.172 -{
  37.173 -    clear_bit(event, &p->shared_info->events);
  37.174 -}
  37.175 -
  37.176 -/* Clear a hypervisor event from a per-domain mask. */
  37.177 -static inline void clear_hyp_event(struct task_struct *p, int event)
  37.178 -{
  37.179 -    clear_bit(event, &p->hyp_events);
  37.180 +        __guest_notify(p);
  37.181  }
  37.182  
  37.183  /* Called on return from (architecture-dependent) entry.S. */
  37.184  void do_hyp_events(void);
  37.185 +
  37.186 +#endif /* __XEN_EVENT_H__ */
    38.1 --- a/xen/include/xen/mm.h	Wed Mar 24 19:05:53 2004 +0000
    38.2 +++ b/xen/include/xen/mm.h	Thu Mar 25 15:02:26 2004 +0000
    38.3 @@ -100,6 +100,7 @@ struct pfn_info
    38.4   /* 28-bit count of references to this frame. */
    38.5  #define PGC_count_mask                ((1<<28)-1)
    38.6  
    38.7 +
    38.8  /* We trust the slab allocator in slab.c, and our use of it. */
    38.9  #define PageSlab(page)		(1)
   38.10  #define PageSetSlab(page)	((void)0)
    39.1 --- a/xen/include/xen/perfc.h	Wed Mar 24 19:05:53 2004 +0000
    39.2 +++ b/xen/include/xen/perfc.h	Thu Mar 25 15:02:26 2004 +0000
    39.3 @@ -11,6 +11,11 @@
    39.4   * PERFCOUNTER_CPU (counter, string, size)    define a counter per CPU
    39.5   * PERFCOUNTER_ARRY (counter, string, size)   define an array of counters
    39.6   * 
    39.7 + * unlike "COUNTERS", "STATUS" variables DO NOT RESET
    39.8 + * PERFSTATUS (counter, string)               define a new performance stauts
    39.9 + * PERFSTATUS_CPU (counter, string, size)     define a status var per CPU
   39.10 + * PERFSTATUS_ARRY (counter, string, size)    define an array of status vars
   39.11 + * 
   39.12   * unsigned long perfc_value  (counter)        get value of a counter  
   39.13   * unsigned long perfc_valuec (counter)        get value of a per CPU counter
   39.14   * unsigned long perfc_valuea (counter, index) get value of an array counter
   39.15 @@ -32,6 +37,12 @@
   39.16    atomic_t var[NR_CPUS];
   39.17  #define PERFCOUNTER_ARRAY( var, name, size ) \
   39.18    atomic_t var[size];
   39.19 +#define PERFSTATUS( var, name ) \
   39.20 +  atomic_t var[1];
   39.21 +#define PERFSTATUS_CPU( var, name ) \
   39.22 +  atomic_t var[NR_CPUS];
   39.23 +#define PERFSTATUS_ARRAY( var, name, size ) \
   39.24 +  atomic_t var[size];
   39.25  
   39.26  struct perfcounter_t 
   39.27  {
   39.28 @@ -47,6 +58,7 @@ extern struct perfcounter_t perfcounters
   39.29  #define perfc_setc(x,v)   atomic_set(&perfcounters.x[smp_processor_id()], v)
   39.30  #define perfc_seta(x,y,v) atomic_set(&perfcounters.x[y], v)
   39.31  #define perfc_incr(x)     atomic_inc(&perfcounters.x[0])
   39.32 +#define perfc_decr(x)     atomic_dec(&perfcounters.x[0])
   39.33  #define perfc_incrc(x)    atomic_inc(&perfcounters.x[smp_processor_id()])
   39.34  #define perfc_incra(x,y)  atomic_inc(&perfcounters.x[y])
   39.35  #define perfc_add(x,y)    atomic_add((y), &perfcounters.x[0])
    40.1 --- a/xen/include/xen/perfc_defn.h	Wed Mar 24 19:05:53 2004 +0000
    40.2 +++ b/xen/include/xen/perfc_defn.h	Thu Mar 25 15:02:26 2004 +0000
    40.3 @@ -19,6 +19,17 @@ PERFCOUNTER_CPU( need_flush_tlb_flush, "
    40.4  
    40.5  PERFCOUNTER_CPU( calls_to_mmu_update, "calls_to_mmu_update" )
    40.6  PERFCOUNTER_CPU( num_page_updates, "num_page_updates" )
    40.7 -
    40.8 +PERFCOUNTER_CPU( calls_to_update_va, "calls_to_update_va_map" )
    40.9 +PERFCOUNTER_CPU( page_faults, "page faults" )
   40.10 +PERFCOUNTER_CPU( copy_user_faults, "copy_user faults" )
   40.11 +PERFCOUNTER_CPU( map_domain_mem_count, "map_domain_mem count" )
   40.12  
   40.13 +PERFCOUNTER_CPU( shadow_l2_table_count, "shadow_l2_table count" )
   40.14 +PERFCOUNTER_CPU( shadow_l1_table_count, "shadow_l1_table count" )
   40.15 +PERFCOUNTER_CPU( unshadow_table_count, "unshadow_table count" )
   40.16 +PERFCOUNTER_CPU( shadow_fixup_count, "shadow_fixup count" )
   40.17 +PERFCOUNTER_CPU( shadow_update_va_fail, "shadow_update_va_fail" )
   40.18  
   40.19 +/* STATUS counters do not reset when 'P' is hit */
   40.20 +PERFSTATUS( shadow_l2_pages, "current # shadow L2 pages" )
   40.21 +PERFSTATUS( shadow_l1_pages, "current # shadow L1 pages" )
    41.1 --- a/xen/include/xen/sched.h	Wed Mar 24 19:05:53 2004 +0000
    41.2 +++ b/xen/include/xen/sched.h	Thu Mar 25 15:02:26 2004 +0000
    41.3 @@ -51,14 +51,25 @@ struct task_struct;
    41.4  
    41.5  typedef struct event_channel_st
    41.6  {
    41.7 -    struct task_struct *remote_dom;
    41.8 -    u16                 remote_port;
    41.9 -#define ECS_FREE         0 /* Available for use.                            */
   41.10 -#define ECS_DISCONNECTED 1 /* Connection is closed. Remote is disconnected. */
   41.11 -#define ECS_CONNECTED    2 /* Connected to remote end.                      */
   41.12 -    u16                 state;
   41.13 +#define ECS_FREE         0 /* Channel is available for use.                  */
   41.14 +#define ECS_UNBOUND      1 /* Channel is not bound to a particular source.   */
   41.15 +#define ECS_INTERDOMAIN  2 /* Channel is bound to another domain.            */
   41.16 +#define ECS_PIRQ         3 /* Channel is bound to a physical IRQ line.       */
   41.17 +#define ECS_VIRQ         4 /* Channel is bound to a virtual IRQ line.        */
   41.18 +    u16 state;
   41.19 +    union {
   41.20 +        struct {
   41.21 +            u16 port;
   41.22 +            struct task_struct *dom;
   41.23 +        } __attribute__ ((packed)) remote; /* state == ECS_CONNECTED */
   41.24 +        u16 pirq; /* state == ECS_PIRQ */
   41.25 +        u16 virq; /* state == ECS_VIRQ */
   41.26 +    } u;
   41.27  } event_channel_t;
   41.28  
   41.29 +int  init_event_channels(struct task_struct *p);
   41.30 +void destroy_event_channels(struct task_struct *p);
   41.31 +
   41.32  struct task_struct 
   41.33  {
   41.34      /*
   41.35 @@ -145,6 +156,14 @@ struct task_struct
   41.36      unsigned int     max_event_channel;
   41.37      spinlock_t       event_channel_lock;
   41.38  
   41.39 +    /*
   41.40 +     * Interrupt to event-channel mappings. Updates should be protected by the 
   41.41 +     * domain's event-channel spinlock. Read accesses can also synchronise on 
   41.42 +     * the lock, but races don't usually matter.
   41.43 +     */
   41.44 +    u16 pirq_to_evtchn[64];
   41.45 +    u16 virq_to_evtchn[NR_VIRQS];
   41.46 +
   41.47      /* Physical I/O */
   41.48      spinlock_t       pcidev_lock;
   41.49      struct list_head pcidev_list;
   41.50 @@ -272,8 +291,9 @@ static inline long schedule_timeout(long
   41.51  }
   41.52  
   41.53  #define signal_pending(_p) \
   41.54 -    ((_p)->hyp_events ||   \
   41.55 -     ((_p)->shared_info->events & (_p)->shared_info->events_mask))
   41.56 +    (((_p)->hyp_events != 0) ||                                 \
   41.57 +     (test_bit(0, &(_p)->shared_info->evtchn_upcall_pending) && \
   41.58 +      !test_bit(0, &(_p)->shared_info->evtchn_upcall_mask)))
   41.59  
   41.60  void domain_init(void);
   41.61  
    42.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    42.2 +++ b/xen/include/xen/shadow.h	Thu Mar 25 15:02:26 2004 +0000
    42.3 @@ -0,0 +1,345 @@
    42.4 +/* -*-  Mode:C; c-basic-offset:4; tab-width:4 -*- */
    42.5 +
    42.6 +#ifndef _XENO_SHADOW_H
    42.7 +#define _XENO_SHADOW_H
    42.8 +
    42.9 +#include <xen/config.h>
   42.10 +#include <xen/types.h>
   42.11 +#include <xen/mm.h>
   42.12 +#include <xen/perfc.h>
   42.13 +
   42.14 +/* Shadow PT flag bits in pfn_info */
   42.15 +#define PSH_shadowed	(1<<31) /* page has a shadow. PFN points to shadow */
   42.16 +#define PSH_pending	    (1<<29) /* page is in the process of being shadowed */
   42.17 +#define PSH_pfn_mask	((1<<21)-1)
   42.18 +
   42.19 +/* Shadow PT operation mode : shadowmode variable in mm_struct */
   42.20 +#define SHM_test        (1<<0) /* just run domain on shadow PTs */
   42.21 +#define SHM_logdirty    (1<<1) /* log pages that are dirtied */
   42.22 +#define SHM_cow         (1<<2) /* copy on write all dirtied pages */
   42.23 +#define SHM_translate   (1<<3) /* lookup machine pages in translation table */
   42.24 +
   42.25 +#define shadow_linear_pg_table ((l1_pgentry_t *)SH_LINEAR_PT_VIRT_START)
   42.26 +#define shadow_linear_l2_table ((l2_pgentry_t *)(SH_LINEAR_PT_VIRT_START+(SH_LINEAR_PT_VIRT_START>>(L2_PAGETABLE_SHIFT-L1_PAGETABLE_SHIFT))))
   42.27 +
   42.28 +extern int shadow_mode_control( struct task_struct *p, unsigned int op );
   42.29 +extern pagetable_t shadow_mk_pagetable( struct task_struct *p, 
   42.30 +										unsigned long gptbase);
   42.31 +extern int shadow_fault( unsigned long va, long error_code );
   42.32 +extern void shadow_l1_normal_pt_update( unsigned long pa, unsigned long gpte, 
   42.33 +										unsigned long *prev_spfn_ptr,
   42.34 +										l1_pgentry_t **prev_spl1e_ptr  );
   42.35 +extern void shadow_l2_normal_pt_update( unsigned long pa, unsigned long gpte );
   42.36 +extern void unshadow_table( unsigned long gpfn, unsigned int type );
   42.37 +extern int shadow_mode_enable( struct task_struct *p, unsigned int mode );
   42.38 +
   42.39 +#define SHADOW_DEBUG 0
   42.40 +#define SHADOW_HASH_DEBUG 0
   42.41 +#define SHADOW_OPTIMISE 1
   42.42 +
   42.43 +struct shadow_status {
   42.44 +    unsigned long pfn;            // gpfn 
   42.45 +    unsigned long spfn_and_flags; // spfn plus flags
   42.46 +    struct shadow_status *next;   // use pull-to-front list.
   42.47 +};
   42.48 +
   42.49 +#define shadow_ht_extra_size         128 /*128*/
   42.50 +#define shadow_ht_buckets            256 /*256*/
   42.51 +
   42.52 +#ifndef NDEBUG
   42.53 +#define SH_LOG(_f, _a...)                             \
   42.54 +  printk("DOM%llu: (file=shadow.c, line=%d) " _f "\n", \
   42.55 +         current->domain , __LINE__ , ## _a )
   42.56 +#else
   42.57 +#define SH_LOG(_f, _a...) 
   42.58 +#endif
   42.59 +
   42.60 +#if SHADOW_DEBUG
   42.61 +#define SH_VLOG(_f, _a...)                             \
   42.62 +  printk("DOM%llu: (file=shadow.c, line=%d) " _f "\n", \
   42.63 +         current->domain , __LINE__ , ## _a )
   42.64 +#else
   42.65 +#define SH_VLOG(_f, _a...) 
   42.66 +#endif
   42.67 +
   42.68 +#if 0
   42.69 +#define SH_VVLOG(_f, _a...)                             \
   42.70 +  printk("DOM%llu: (file=shadow.c, line=%d) " _f "\n", \
   42.71 +         current->domain , __LINE__ , ## _a )
   42.72 +#else
   42.73 +#define SH_VVLOG(_f, _a...) 
   42.74 +#endif
   42.75 +
   42.76 +
   42.77 +
   42.78 +#if SHADOW_HASH_DEBUG
   42.79 +static void shadow_audit(struct task_struct *p, int print)
   42.80 +{
   42.81 +	int live=0, free=0, j=0, abs;
   42.82 +	struct shadow_status *a;
   42.83 +	
   42.84 +    for(j=0;j<shadow_ht_buckets;j++)
   42.85 +    {
   42.86 +        a = &p->mm.shadow_ht[j];        
   42.87 +		if(a->pfn) live++;
   42.88 +        while(a->next && live<9999)
   42.89 +		{ 
   42.90 +			live++; 
   42.91 +			if(a->pfn == 0)
   42.92 +			{
   42.93 +				printk("XXX live=%d pfn=%08lx sp=%08lx next=%p\n",
   42.94 +					   live, a->pfn, a->spfn_and_flags, a->next);
   42.95 +				BUG();
   42.96 +			}
   42.97 +			a=a->next; 
   42.98 +		}
   42.99 +		ASSERT(live<9999);
  42.100 +	}
  42.101 +
  42.102 +    a = p->mm.shadow_ht_free;
  42.103 +    while(a) { free++; a=a->next; }
  42.104 +
  42.105 +    if(print) printk("live=%d free=%d\n",live,free);
  42.106 +
  42.107 +	abs=(perfc_value(shadow_l1_pages)+perfc_value(shadow_l2_pages))-live;
  42.108 +	if( abs < -1 || abs > 1 )
  42.109 +	{
  42.110 +		printk("live=%d free=%d l1=%d l2=%d\n",live,free,
  42.111 +			  perfc_value(shadow_l1_pages), perfc_value(shadow_l2_pages) );
  42.112 +		BUG();
  42.113 +    }
  42.114 +
  42.115 +}
  42.116 +
  42.117 +#else
  42.118 +#define shadow_audit(p, print)
  42.119 +#endif
  42.120 +
  42.121 +static inline struct shadow_status* hash_bucket( struct task_struct *p,
  42.122 +												 unsigned int gpfn )
  42.123 +{
  42.124 +    return &(p->mm.shadow_ht[gpfn % shadow_ht_buckets]);
  42.125 +}
  42.126 +
  42.127 +
  42.128 +static inline unsigned long __shadow_status( struct task_struct *p,
  42.129 +										   unsigned int gpfn )
  42.130 +{
  42.131 +	struct shadow_status **ob, *b, *B = hash_bucket( p, gpfn );
  42.132 +
  42.133 +    b = B;
  42.134 +    ob = NULL;
  42.135 +
  42.136 +	SH_VVLOG("lookup gpfn=%08lx bucket=%08lx", gpfn, b );
  42.137 +	shadow_audit(p,0);  // if in debug mode
  42.138 +
  42.139 +	do
  42.140 +	{
  42.141 +		if ( b->pfn == gpfn )
  42.142 +		{
  42.143 +			unsigned long t;
  42.144 +			struct shadow_status *x;
  42.145 +
  42.146 +			// swap with head
  42.147 +			t=B->pfn; B->pfn=b->pfn; b->pfn=t;
  42.148 +			t=B->spfn_and_flags; B->spfn_and_flags=b->spfn_and_flags; 
  42.149 +			    b->spfn_and_flags=t;
  42.150 +
  42.151 +			if(ob)
  42.152 +			{   // pull to front
  42.153 +				*ob=b->next;
  42.154 +				x=B->next;
  42.155 +				B->next=b;	
  42.156 +				b->next=x;
  42.157 +			}			
  42.158 +			return B->spfn_and_flags;
  42.159 +		}
  42.160 +#if SHADOW_HASH_DEBUG
  42.161 +		else
  42.162 +		{
  42.163 +			if(b!=B)ASSERT(b->pfn);
  42.164 +		}
  42.165 +#endif
  42.166 +		ob=&b->next;
  42.167 +		b=b->next;
  42.168 +	}
  42.169 +	while (b);
  42.170 +
  42.171 +	return 0;
  42.172 +}
  42.173 +
  42.174 +/* we can make this locking more fine grained e.g. per shadow page if it 
  42.175 +ever becomes a problem, but since we need a spin lock on the hash table 
  42.176 +anyway its probably not worth being too clever. */
  42.177 +
  42.178 +static inline unsigned long get_shadow_status( struct task_struct *p,
  42.179 +										   unsigned int gpfn )
  42.180 +{
  42.181 +	unsigned long res;
  42.182 +
  42.183 +	spin_lock(&p->mm.shadow_lock);
  42.184 +	res = __shadow_status( p, gpfn );
  42.185 +	if (!res) spin_unlock(&p->mm.shadow_lock);
  42.186 +	return res;
  42.187 +}
  42.188 +
  42.189 +
  42.190 +static inline void put_shadow_status( struct task_struct *p )
  42.191 +{
  42.192 +	spin_unlock(&p->mm.shadow_lock);
  42.193 +}
  42.194 +
  42.195 +
  42.196 +static inline void delete_shadow_status( struct task_struct *p,
  42.197 +									  unsigned int gpfn )
  42.198 +{
  42.199 +	struct shadow_status *b, *B, **ob;
  42.200 +
  42.201 +	B = b = hash_bucket( p, gpfn );
  42.202 +
  42.203 +	SH_VVLOG("delete gpfn=%08x bucket=%p", gpfn, b );
  42.204 +	shadow_audit(p,0);
  42.205 +	ASSERT(gpfn);
  42.206 +
  42.207 +	if( b->pfn == gpfn )
  42.208 +    {
  42.209 +		if (b->next)
  42.210 +		{
  42.211 +			struct shadow_status *D=b->next;
  42.212 +			b->spfn_and_flags = b->next->spfn_and_flags;
  42.213 +			b->pfn = b->next->pfn;
  42.214 +
  42.215 +			b->next = b->next->next;
  42.216 +			D->next = p->mm.shadow_ht_free;
  42.217 +			p->mm.shadow_ht_free = D;
  42.218 +		}
  42.219 +		else
  42.220 +		{
  42.221 +			b->pfn = 0;
  42.222 +			b->spfn_and_flags = 0;
  42.223 +		}
  42.224 +
  42.225 +#if SHADOW_HASH_DEBUG
  42.226 +		if( __shadow_status(p,gpfn) ) BUG();  
  42.227 +#endif
  42.228 +		return;
  42.229 +    }
  42.230 +
  42.231 +	ob = &b->next;
  42.232 +	b=b->next;
  42.233 +
  42.234 +	do
  42.235 +	{
  42.236 +		if ( b->pfn == gpfn )			
  42.237 +		{
  42.238 +			b->pfn = 0;
  42.239 +			b->spfn_and_flags = 0;
  42.240 +
  42.241 +			// b is in the list
  42.242 +            *ob=b->next;
  42.243 +			b->next = p->mm.shadow_ht_free;
  42.244 +			p->mm.shadow_ht_free = b;
  42.245 +
  42.246 +#if SHADOW_HASH_DEBUG
  42.247 +			if( __shadow_status(p,gpfn) ) BUG();
  42.248 +#endif
  42.249 +			return;
  42.250 +		}
  42.251 +
  42.252 +		ob = &b->next;
  42.253 +		b=b->next;
  42.254 +	}
  42.255 +	while (b);
  42.256 +
  42.257 +	// if we got here, it wasn't in the list
  42.258 +    BUG();
  42.259 +}
  42.260 +
  42.261 +
  42.262 +static inline void set_shadow_status( struct task_struct *p,
  42.263 +									  unsigned int gpfn, unsigned long s )
  42.264 +{
  42.265 +	struct shadow_status *b, *B, *extra, **fptr;
  42.266 +    int i;
  42.267 +
  42.268 +	B = b = hash_bucket( p, gpfn );
  42.269 +   
  42.270 +    ASSERT(gpfn);
  42.271 +    ASSERT(s);
  42.272 +    SH_VVLOG("set gpfn=%08x s=%08lx bucket=%p(%p)", gpfn, s, b, b->next );
  42.273 +    shadow_audit(p,0);
  42.274 +
  42.275 +	do
  42.276 +	{
  42.277 +		if ( b->pfn == gpfn )			
  42.278 +		{
  42.279 +			b->spfn_and_flags = s;
  42.280 +			return;
  42.281 +		}
  42.282 +
  42.283 +		b=b->next;
  42.284 +	}
  42.285 +	while (b);
  42.286 +
  42.287 +	// if we got here, this is an insert rather than update
  42.288 +
  42.289 +    ASSERT( s );  // deletes must have succeeded by here
  42.290 +
  42.291 +    if ( B->pfn == 0 )
  42.292 +	{
  42.293 +		// we can use this head
  42.294 +        ASSERT( B->next == 0 );
  42.295 +		B->pfn = gpfn;
  42.296 +		B->spfn_and_flags = s;
  42.297 +		return;
  42.298 +	}
  42.299 +
  42.300 +    if( unlikely(p->mm.shadow_ht_free == NULL) )
  42.301 +    {
  42.302 +        SH_LOG("allocate more shadow hashtable blocks");
  42.303 +
  42.304 +        // we need to allocate more space
  42.305 +        extra = kmalloc( sizeof(void*) + (shadow_ht_extra_size * 
  42.306 +							   sizeof(struct shadow_status)), GFP_KERNEL );
  42.307 +
  42.308 +	    if( ! extra ) BUG(); // should be more graceful here....
  42.309 +
  42.310 +	    memset( extra, 0, sizeof(void*) + (shadow_ht_extra_size * 
  42.311 +							   sizeof(struct shadow_status)) );
  42.312 +	
  42.313 +        // add extras to free list
  42.314 +	    fptr = &p->mm.shadow_ht_free;
  42.315 +	    for ( i=0; i<shadow_ht_extra_size; i++ )
  42.316 + 	    {
  42.317 +		    *fptr = &extra[i];
  42.318 +		    fptr = &(extra[i].next);
  42.319 +	    }
  42.320 +	    *fptr = NULL;
  42.321 +
  42.322 +	    *((struct shadow_status ** ) &p->mm.shadow_ht[shadow_ht_extra_size]) = 
  42.323 +                                            p->mm.shadow_ht_extras;
  42.324 +        p->mm.shadow_ht_extras = extra;
  42.325 +
  42.326 +    }
  42.327 +
  42.328 +	// should really put this in B to go right to front
  42.329 +	b = p->mm.shadow_ht_free;
  42.330 +    p->mm.shadow_ht_free = b->next;
  42.331 +    b->spfn_and_flags = s;
  42.332 +	b->pfn = gpfn;
  42.333 +	b->next = B->next;
  42.334 +	B->next = b;
  42.335 +
  42.336 +	return;
  42.337 +}
  42.338 +
  42.339 +
  42.340 +
  42.341 +#if SHADOW_DEBUG
  42.342 +extern int check_pagetable( struct task_struct *p, pagetable_t pt, char *s );
  42.343 +#else
  42.344 +#define check_pagetable( p, pt, s )
  42.345 +#endif
  42.346 +
  42.347 +
  42.348 +#endif
    43.1 --- a/xen/net/dev.c	Wed Mar 24 19:05:53 2004 +0000
    43.2 +++ b/xen/net/dev.c	Thu Mar 25 15:02:26 2004 +0000
    43.3 @@ -28,6 +28,7 @@
    43.4  #include <xen/init.h>
    43.5  #include <xen/module.h>
    43.6  #include <xen/event.h>
    43.7 +#include <xen/shadow.h>
    43.8  #include <asm/domain_page.h>
    43.9  #include <asm/pgalloc.h>
   43.10  #include <asm/io.h>
   43.11 @@ -488,11 +489,12 @@ struct netif_rx_stats netdev_rx_stat[NR_
   43.12  void deliver_packet(struct sk_buff *skb, net_vif_t *vif)
   43.13  {
   43.14      rx_shadow_entry_t *rx;
   43.15 -    unsigned long *ptep, pte; 
   43.16 +    unsigned long *ptep, pte, new_pte; 
   43.17      struct pfn_info *old_page, *new_page, *pte_page;
   43.18      unsigned short size;
   43.19      unsigned char  offset, status = RING_STATUS_OK;
   43.20      struct task_struct *p = vif->domain;
   43.21 +    unsigned long spte_pfn;
   43.22  
   43.23      memcpy(skb->mac.ethernet->h_dest, vif->vmac, ETH_ALEN);
   43.24      if ( ntohs(skb->mac.ethernet->h_proto) == ETH_P_ARP )
   43.25 @@ -530,10 +532,12 @@ void deliver_packet(struct sk_buff *skb,
   43.26      wmb(); /* Get type count and set flush bit before updating PTE. */
   43.27  
   43.28      pte = *ptep;
   43.29 +
   43.30 +    new_pte = (pte & ~PAGE_MASK) | _PAGE_RW | _PAGE_PRESENT |
   43.31 +                          ((new_page - frame_table) << PAGE_SHIFT);
   43.32 +
   43.33      if ( unlikely(pte & _PAGE_PRESENT) || 
   43.34 -         unlikely(cmpxchg(ptep, pte, 
   43.35 -                          (pte & ~PAGE_MASK) | _PAGE_RW | _PAGE_PRESENT |
   43.36 -                          ((new_page - frame_table) << PAGE_SHIFT))) != pte )
   43.37 +         unlikely(cmpxchg(ptep, pte, new_pte)) != pte )
   43.38      {
   43.39          DPRINTK("PTE was modified or reused! %08lx %08lx\n", pte, *ptep);
   43.40          unmap_domain_mem(ptep);
   43.41 @@ -543,6 +547,19 @@ void deliver_packet(struct sk_buff *skb,
   43.42          goto out;
   43.43      }
   43.44  
   43.45 +    if ( p->mm.shadow_mode && 
   43.46 +	 (spte_pfn=get_shadow_status(p, pte_page-frame_table)) )
   43.47 +    {
   43.48 +	unsigned long *sptr = map_domain_mem( (spte_pfn<<PAGE_SHIFT) |
   43.49 +			(((unsigned long)ptep)&~PAGE_MASK) );
   43.50 +
   43.51 +        // avoid the fault later
   43.52 +	*sptr = new_pte;
   43.53 +
   43.54 +	unmap_domain_mem(sptr);
   43.55 +	put_shadow_status(p);
   43.56 +    }
   43.57 +
   43.58      machine_to_phys_mapping[new_page - frame_table] 
   43.59          = machine_to_phys_mapping[old_page - frame_table];
   43.60      
   43.61 @@ -2049,7 +2066,7 @@ static void get_rx_bufs(net_vif_t *vif)
   43.62      rx_shadow_entry_t *srx;
   43.63      unsigned long  pte_pfn, buf_pfn;
   43.64      struct pfn_info *pte_page, *buf_page;
   43.65 -    unsigned long *ptep, pte;
   43.66 +    unsigned long *ptep, pte, spfn;
   43.67  
   43.68      spin_lock(&vif->rx_lock);
   43.69  
   43.70 @@ -2068,6 +2085,8 @@ static void get_rx_bufs(net_vif_t *vif)
   43.71  
   43.72          pte_pfn  = rx.addr >> PAGE_SHIFT;
   43.73          pte_page = &frame_table[pte_pfn];
   43.74 +
   43.75 +	//printk("MMM %08lx ", rx.addr);
   43.76              
   43.77          /* The address passed down must be to a valid PTE. */
   43.78          if ( unlikely(pte_pfn >= max_page) ||
   43.79 @@ -2081,7 +2100,7 @@ static void get_rx_bufs(net_vif_t *vif)
   43.80          
   43.81          ptep = map_domain_mem(rx.addr);
   43.82          pte  = *ptep;
   43.83 -        
   43.84 +	//printk("%08lx\n",pte);        
   43.85          /* We must be passed a valid writeable mapping to swizzle. */
   43.86          if ( unlikely((pte & (_PAGE_PRESENT|_PAGE_RW)) != 
   43.87                        (_PAGE_PRESENT|_PAGE_RW)) ||
   43.88 @@ -2092,6 +2111,17 @@ static void get_rx_bufs(net_vif_t *vif)
   43.89              make_rx_response(vif, rx.id, 0, RING_STATUS_BAD_PAGE, 0);
   43.90              goto rx_unmap_and_continue;
   43.91          }
   43.92 +
   43.93 +	if ( p->mm.shadow_mode && 
   43.94 +	     (spfn=get_shadow_status(p, rx.addr>>PAGE_SHIFT)) )
   43.95 +	  {
   43.96 +	    unsigned long * sptr = 
   43.97 +	      map_domain_mem( (spfn<<PAGE_SHIFT) | (rx.addr&~PAGE_MASK) );
   43.98 +
   43.99 +	    *sptr = 0;
  43.100 +	    unmap_domain_mem( sptr );
  43.101 +	    put_shadow_status(p);
  43.102 +	  }
  43.103          
  43.104          buf_pfn  = pte >> PAGE_SHIFT;
  43.105          buf_page = &frame_table[buf_pfn];
  43.106 @@ -2112,6 +2142,8 @@ static void get_rx_bufs(net_vif_t *vif)
  43.107              put_page_and_type(pte_page);
  43.108              make_rx_response(vif, rx.id, 0, RING_STATUS_BAD_PAGE, 0);
  43.109              goto rx_unmap_and_continue;
  43.110 +
  43.111 +	    // XXX IAP should SHADOW_CONFIG do something here?
  43.112          }
  43.113  
  43.114          /*
  43.115 @@ -2335,10 +2367,7 @@ static void make_tx_response(net_vif_t  
  43.116  
  43.117      smp_mb(); /* Update producer before checking event threshold. */
  43.118      if ( i == vif->shared_idxs->tx_event )
  43.119 -    {
  43.120 -        unsigned long cpu_mask = mark_guest_event(vif->domain, _EVENT_NET);
  43.121 -        guest_event_notify(cpu_mask);    
  43.122 -    }
  43.123 +        send_guest_virq(vif->domain, VIRQ_NET);
  43.124  }
  43.125  
  43.126  
  43.127 @@ -2361,10 +2390,7 @@ static void make_rx_response(net_vif_t  
  43.128  
  43.129      smp_mb(); /* Update producer before checking event threshold. */
  43.130      if ( i == vif->shared_idxs->rx_event )
  43.131 -    {
  43.132 -        unsigned long cpu_mask = mark_guest_event(vif->domain, _EVENT_NET);
  43.133 -        guest_event_notify(cpu_mask);    
  43.134 -    }
  43.135 +        send_guest_virq(vif->domain, VIRQ_NET);
  43.136  }
  43.137  
  43.138  
    44.1 --- a/xenolinux-2.4.25-sparse/arch/xen/drivers/block/block.c	Wed Mar 24 19:05:53 2004 +0000
    44.2 +++ b/xenolinux-2.4.25-sparse/arch/xen/drivers/block/block.c	Thu Mar 25 15:02:26 2004 +0000
    44.3 @@ -18,15 +18,14 @@
    44.4  
    44.5  typedef unsigned char byte; /* from linux/ide.h */
    44.6  
    44.7 -#define XLBLK_RESPONSE_IRQ HYPEREVENT_IRQ(_EVENT_BLKDEV)
    44.8 -#define XLBLK_UPDATE_IRQ   HYPEREVENT_IRQ(_EVENT_VBD_UPD)
    44.9 -#define DEBUG_IRQ          HYPEREVENT_IRQ(_EVENT_DEBUG)
   44.10 -
   44.11  #define STATE_ACTIVE    0
   44.12  #define STATE_SUSPENDED 1
   44.13  #define STATE_CLOSED    2
   44.14  static unsigned int state = STATE_SUSPENDED;
   44.15  
   44.16 +/* Dynamically-mapped IRQs. */
   44.17 +static int xlblk_response_irq, xlblk_update_irq;
   44.18 +
   44.19  static blk_ring_t *blk_ring;
   44.20  static BLK_RING_IDX resp_cons; /* Response consumer for comms ring. */
   44.21  static BLK_RING_IDX req_prod;  /* Private request producer.         */
   44.22 @@ -552,7 +551,10 @@ int __init xlblk_init(void)
   44.23  
   44.24      reset_xlblk_interface();
   44.25  
   44.26 -    error = request_irq(XLBLK_RESPONSE_IRQ, xlblk_response_int, 
   44.27 +    xlblk_response_irq = bind_virq_to_irq(VIRQ_BLKDEV);
   44.28 +    xlblk_update_irq   = bind_virq_to_irq(VIRQ_VBD_UPD);
   44.29 +
   44.30 +    error = request_irq(xlblk_response_irq, xlblk_response_int, 
   44.31                          SA_SAMPLE_RANDOM, "blkdev", NULL);
   44.32      if ( error )
   44.33      {
   44.34 @@ -560,8 +562,8 @@ int __init xlblk_init(void)
   44.35          goto fail;
   44.36      }
   44.37  
   44.38 -    error = request_irq(XLBLK_UPDATE_IRQ, xlblk_update_int,
   44.39 -                        SA_INTERRUPT, "blkdev", NULL);
   44.40 +    error = request_irq(xlblk_update_irq, xlblk_update_int,
   44.41 +                        0, "blkdev", NULL);
   44.42  
   44.43      if ( error )
   44.44      {
   44.45 @@ -581,8 +583,10 @@ int __init xlblk_init(void)
   44.46  static void __exit xlblk_cleanup(void)
   44.47  {
   44.48      xlvbd_cleanup();
   44.49 -    free_irq(XLBLK_RESPONSE_IRQ, NULL);
   44.50 -    free_irq(XLBLK_UPDATE_IRQ, NULL);
   44.51 +    free_irq(xlblk_response_irq, NULL);
   44.52 +    free_irq(xlblk_update_irq, NULL);
   44.53 +    unbind_virq_from_irq(VIRQ_BLKDEV);
   44.54 +    unbind_virq_from_irq(VIRQ_VBD_UPD);
   44.55  }
   44.56  
   44.57  
    45.1 --- a/xenolinux-2.4.25-sparse/arch/xen/drivers/console/console.c	Wed Mar 24 19:05:53 2004 +0000
    45.2 +++ b/xenolinux-2.4.25-sparse/arch/xen/drivers/console/console.c	Thu Mar 25 15:02:26 2004 +0000
    45.3 @@ -32,6 +32,8 @@
    45.4  
    45.5  static spinlock_t xen_console_lock = SPIN_LOCK_UNLOCKED;
    45.6  
    45.7 +static int console_evtchn;
    45.8 +
    45.9  #define XEN_TTY_MINOR 123
   45.10  
   45.11  /******************** Kernel console driver ********************************/
   45.12 @@ -65,7 +67,7 @@ static void nonpriv_conwrite(const char 
   45.13          
   45.14          ctrl_if->tx_req_prod++;
   45.15          evtchn_op.cmd = EVTCHNOP_send;
   45.16 -        evtchn_op.u.send.local_port = 0;
   45.17 +        evtchn_op.u.send.local_port = console_evtchn;
   45.18          (void)HYPERVISOR_event_channel_op(&evtchn_op);
   45.19          
   45.20          s     += src;
   45.21 @@ -118,7 +120,36 @@ static struct console kcons_info = {
   45.22  
   45.23  void xen_console_init(void)
   45.24  {
   45.25 +    evtchn_op_t op;
   45.26 +    int i;
   45.27 +
   45.28 +    if ( !(start_info.flags & SIF_INITDOMAIN) )
   45.29 +    {
   45.30 +        /* Scan the event-channel space to find our control link to DOM0. */
   45.31 +        for ( i = 0; i < NR_EVENT_CHANNELS; i++ )
   45.32 +        {
   45.33 +            op.cmd           = EVTCHNOP_status;
   45.34 +            op.u.status.dom  = DOMID_SELF;
   45.35 +            op.u.status.port = i;
   45.36 +            if ( (HYPERVISOR_event_channel_op(&op) == 0) &&
   45.37 +                 (op.u.status.status == EVTCHNSTAT_interdomain) &&
   45.38 +                 (op.u.status.u.interdomain.dom == 0) )
   45.39 +                break;
   45.40 +        }
   45.41 +        
   45.42 +        /* Bug out if there is no control link. */
   45.43 +        if ( (console_evtchn = i) == NR_EVENT_CHANNELS )
   45.44 +            BUG();
   45.45 +    }
   45.46 +
   45.47      register_console(&kcons_info);
   45.48 +
   45.49 +    /*
   45.50 +     * XXX This prevents a bogus 'VIRQ_ERROR' when interrupts are enabled
   45.51 +     * for the first time. This works because by this point all important
   45.52 +     * VIRQs (eg. timer) have been properly bound.
   45.53 +     */
   45.54 +    clear_bit(0, &HYPERVISOR_shared_info->evtchn_pending[0]);
   45.55  }
   45.56  
   45.57  
   45.58 @@ -149,6 +180,7 @@ static struct tty_struct *xen_console_ta
   45.59  static struct termios *xen_console_termios[1];
   45.60  static struct termios *xen_console_termios_locked[1];
   45.61  static struct tty_struct *xen_console_tty;
   45.62 +static int console_irq;
   45.63  
   45.64  #define WBUF_SIZE     1024
   45.65  #define WBUF_MASK(_i) ((_i)&(WBUF_SIZE-1))
   45.66 @@ -194,9 +226,6 @@ static void __do_console_io(void)
   45.67          return;
   45.68      }
   45.69  
   45.70 -    /* Acknowledge the notification. */
   45.71 -    evtchn_clear_port(0);
   45.72 -
   45.73      ctrl_if = (control_if_t *)((char *)HYPERVISOR_shared_info + 2048);
   45.74      
   45.75      /* Receive work. */
   45.76 @@ -254,22 +283,12 @@ static void __do_console_io(void)
   45.77      {
   45.78          /* Send a notification to the controller. */
   45.79          evtchn_op.cmd = EVTCHNOP_send;
   45.80 -        evtchn_op.u.send.local_port = 0;
   45.81 +        evtchn_op.u.send.local_port = console_evtchn;
   45.82          (void)HYPERVISOR_event_channel_op(&evtchn_op);
   45.83      }
   45.84  }
   45.85  
   45.86 -/* This is the callback entry point for domains != 0. */
   45.87 -static void control_event(unsigned int port)
   45.88 -{
   45.89 -    unsigned long flags;
   45.90 -    spin_lock_irqsave(&xen_console_lock, flags);
   45.91 -    __do_console_io();
   45.92 -    spin_unlock_irqrestore(&xen_console_lock, flags);
   45.93 -}
   45.94 -
   45.95 -/* This is the callback entry point for domain 0. */
   45.96 -static void control_irq(int irq, void *dev_id, struct pt_regs *regs)
   45.97 +static void console_interrupt(int irq, void *dev_id, struct pt_regs *regs)
   45.98  {
   45.99      unsigned long flags;
  45.100      spin_lock_irqsave(&xen_console_lock, flags);
  45.101 @@ -472,17 +491,12 @@ int __init xen_con_init(void)
  45.102          panic("Couldn't register Xen virtual console driver\n");
  45.103  
  45.104      if ( !(start_info.flags & SIF_INITDOMAIN) )
  45.105 -    {
  45.106 -        if ( evtchn_request_port(0, control_event) != 0 )
  45.107 -            BUG();
  45.108 -        control_event(0); /* kickstart the console */
  45.109 -    }
  45.110 +        console_irq = bind_evtchn_to_irq(console_evtchn);
  45.111      else
  45.112 -    {
  45.113 -        request_irq(HYPEREVENT_IRQ(_EVENT_CONSOLE), 
  45.114 -                    control_irq, 0, "console", NULL);
  45.115 -        control_irq(0, NULL, NULL); /* kickstart the console */
  45.116 -    }
  45.117 +        console_irq = bind_virq_to_irq(VIRQ_CONSOLE);
  45.118 +
  45.119 +    (void)request_irq(console_irq,
  45.120 +                      console_interrupt, 0, "console", NULL);
  45.121  
  45.122      printk("Xen virtual console successfully installed\n");
  45.123      
  45.124 @@ -497,8 +511,12 @@ void __exit xen_con_fini(void)
  45.125      if ( ret != 0 )
  45.126          printk(KERN_ERR "Unable to unregister Xen console driver: %d\n", ret);
  45.127  
  45.128 +    free_irq(console_irq, NULL);
  45.129 +
  45.130      if ( !(start_info.flags & SIF_INITDOMAIN) )
  45.131 -        (void)evtchn_free_port(0);
  45.132 +        unbind_evtchn_from_irq(console_evtchn);
  45.133 +    else
  45.134 +        unbind_virq_from_irq(VIRQ_CONSOLE);
  45.135  }
  45.136  
  45.137  module_init(xen_con_init);
    46.1 --- a/xenolinux-2.4.25-sparse/arch/xen/drivers/evtchn/evtchn.c	Wed Mar 24 19:05:53 2004 +0000
    46.2 +++ b/xenolinux-2.4.25-sparse/arch/xen/drivers/evtchn/evtchn.c	Thu Mar 25 15:02:26 2004 +0000
    46.3 @@ -40,148 +40,54 @@ static unsigned int ring_cons, ring_prod
    46.4  static DECLARE_WAIT_QUEUE_HEAD(evtchn_wait);
    46.5  static struct fasync_struct *evtchn_async_queue;
    46.6  
    46.7 -static evtchn_receiver_t rx_fns[1024];
    46.8 -
    46.9 -static u32 pend_outstanding[32];
   46.10 -static u32 disc_outstanding[32];
   46.11 +/*
   46.12 + * Pending normal notifications and pending exceptional notifications.
   46.13 + * 'Pending' means that we received an upcall but this is not yet ack'ed
   46.14 + * from userspace by writing to /dev/xen/evtchn.
   46.15 + */
   46.16 +static u32 pend_nrm[32], pend_exc[32];
   46.17  
   46.18  static spinlock_t lock;
   46.19  
   46.20 -int evtchn_request_port(unsigned int port, evtchn_receiver_t rx_fn)
   46.21 +void evtchn_device_upcall(int port, int exception)
   46.22  {
   46.23 -    unsigned long flags;
   46.24 -    int rc;
   46.25 -
   46.26 -    spin_lock_irqsave(&lock, flags);
   46.27 +    u16 port_subtype;
   46.28  
   46.29 -    if ( rx_fns[port] != NULL )
   46.30 -    {
   46.31 -        printk(KERN_ALERT "Event channel port %d already in use.\n", port);
   46.32 -        rc = -EINVAL;
   46.33 -    }
   46.34 -    else
   46.35 -    {
   46.36 -        rx_fns[port] = rx_fn;
   46.37 -        rc = 0;
   46.38 -    }
   46.39 -
   46.40 -    spin_unlock_irqrestore(&lock, flags);
   46.41 -
   46.42 -    return rc;
   46.43 -}
   46.44 -
   46.45 -int evtchn_free_port(unsigned int port)
   46.46 -{
   46.47 -    unsigned long flags;
   46.48 -    int rc;
   46.49 -
   46.50 -    spin_lock_irqsave(&lock, flags);
   46.51 +    spin_lock(&lock);
   46.52  
   46.53 -    if ( rx_fns[port] == NULL )
   46.54 -    {
   46.55 -        printk(KERN_ALERT "Event channel port %d not in use.\n", port);
   46.56 -        rc = -EINVAL;
   46.57 -    }
   46.58 -    else
   46.59 -    {
   46.60 -        rx_fns[port] = NULL;
   46.61 -        rc = 0;
   46.62 -    }
   46.63 -
   46.64 -    spin_unlock_irqrestore(&lock, flags);
   46.65 -
   46.66 -    return rc;
   46.67 -}
   46.68 +    mask_evtchn(port);
   46.69  
   46.70 -/*
   46.71 - * NB. Clearing port can race a notification from remote end. Caller must
   46.72 - * therefore recheck notification status on return to avoid missing events.
   46.73 - */
   46.74 -void evtchn_clear_port(unsigned int port)
   46.75 -{
   46.76 -    unsigned int p = port & PORTIDX_MASK;
   46.77 -    unsigned long flags;
   46.78 -
   46.79 -    spin_lock_irqsave(&lock, flags);
   46.80 -
   46.81 -    if ( unlikely(port & PORT_DISCONNECT) )
   46.82 +    if ( likely(!exception) )
   46.83      {
   46.84 -        clear_bit(p, &disc_outstanding[0]);
   46.85 -        clear_bit(p, &HYPERVISOR_shared_info->event_channel_disc[0]);
   46.86 +        clear_evtchn(port);
   46.87 +        set_bit(port, &pend_nrm[0]);
   46.88 +        port_subtype = PORT_NORMAL;
   46.89      }
   46.90      else
   46.91      {
   46.92 -        clear_bit(p, &pend_outstanding[0]);
   46.93 -        clear_bit(p, &HYPERVISOR_shared_info->event_channel_pend[0]);
   46.94 +        clear_evtchn_exception(port);
   46.95 +        set_bit(port, &pend_exc[0]);
   46.96 +        port_subtype = PORT_EXCEPTION;
   46.97      }
   46.98  
   46.99 -    spin_unlock_irqrestore(&lock, flags);
  46.100 -}
  46.101 -
  46.102 -static inline void process_bitmask(u32 *sel, 
  46.103 -                                   u32 *mask,
  46.104 -                                   u32 *outstanding,
  46.105 -                                   unsigned int port_subtype)
  46.106 -{
  46.107 -    unsigned long l1, l2;
  46.108 -    unsigned int  l1_idx, l2_idx, port;
  46.109 -
  46.110 -    l1 = xchg(sel, 0);
  46.111 -    while ( (l1_idx = ffs(l1)) != 0 )
  46.112 +    if ( ring != NULL )
  46.113      {
  46.114 -        l1_idx--;
  46.115 -        l1 &= ~(1 << l1_idx);
  46.116 -
  46.117 -        l2 = mask[l1_idx] & ~outstanding[l1_idx];
  46.118 -        outstanding[l1_idx] |= l2;
  46.119 -        while ( (l2_idx = ffs(l2)) != 0 )
  46.120 +        if ( (ring_prod - ring_cons) < RING_SIZE )
  46.121          {
  46.122 -            l2_idx--;
  46.123 -            l2 &= ~(1 << l2_idx);
  46.124 -
  46.125 -            port = (l1_idx * 32) + l2_idx;
  46.126 -            if ( rx_fns[port] != NULL )
  46.127 -            {
  46.128 -                (*rx_fns[port])(port | port_subtype);
  46.129 -            }
  46.130 -            else if ( ring != NULL )
  46.131 +            ring[RING_MASK(ring_prod)] = (u16)port | port_subtype;
  46.132 +            if ( ring_cons == ring_prod++ )
  46.133              {
  46.134 -                if ( (ring_prod - ring_cons) < RING_SIZE )
  46.135 -                {
  46.136 -                    ring[RING_MASK(ring_prod)] = (u16)(port | port_subtype);
  46.137 -                    if ( ring_cons == ring_prod++ )
  46.138 -                    {
  46.139 -                        wake_up_interruptible(&evtchn_wait);
  46.140 -                        kill_fasync(&evtchn_async_queue, SIGIO, POLL_IN);
  46.141 -                    }
  46.142 -                }
  46.143 -                else
  46.144 -                {
  46.145 -                    ring_overflow = 1;
  46.146 -                }
  46.147 +                wake_up_interruptible(&evtchn_wait);
  46.148 +                kill_fasync(&evtchn_async_queue, SIGIO, POLL_IN);
  46.149              }
  46.150          }
  46.151 +        else
  46.152 +        {
  46.153 +            ring_overflow = 1;
  46.154 +        }
  46.155      }
  46.156 -}
  46.157 -
  46.158 -static void evtchn_interrupt(int irq, void *dev_id, struct pt_regs *regs)
  46.159 -{
  46.160 -    shared_info_t *si = HYPERVISOR_shared_info;
  46.161 -    unsigned long flags;
  46.162 -
  46.163 -    spin_lock_irqsave(&lock, flags);
  46.164  
  46.165 -    process_bitmask(&si->event_channel_pend_sel, 
  46.166 -                    &si->event_channel_pend[0],
  46.167 -                    &pend_outstanding[0],
  46.168 -                    PORT_NORMAL);
  46.169 -        
  46.170 -    process_bitmask(&si->event_channel_disc_sel,
  46.171 -                    &si->event_channel_disc[0],
  46.172 -                    &disc_outstanding[0],
  46.173 -                    PORT_DISCONNECT);
  46.174 -        
  46.175 -    spin_unlock_irqrestore(&lock, flags);
  46.176 +    spin_unlock(&lock);
  46.177  }
  46.178  
  46.179  static void __evtchn_reset_buffer_ring(void)
  46.180 @@ -194,20 +100,18 @@ static void __evtchn_reset_buffer_ring(v
  46.181  
  46.182      for ( i = 0; i < 32; i++ )
  46.183      {
  46.184 -        m = pend_outstanding[i];
  46.185 +        m = pend_exc[i];
  46.186          while ( (j = ffs(m)) != 0 )
  46.187          {
  46.188              m &= ~(1 << --j);
  46.189 -            if ( rx_fns[(i * 32) + j] == NULL )
  46.190 -                ring[ring_prod++] = (u16)(((i * 32) + j) | PORT_NORMAL);
  46.191 +            ring[ring_prod++] = (u16)(((i * 32) + j) | PORT_EXCEPTION);
  46.192          }
  46.193  
  46.194 -        m = disc_outstanding[i];
  46.195 +        m = pend_nrm[i];
  46.196          while ( (j = ffs(m)) != 0 )
  46.197          {
  46.198              m &= ~(1 << --j);
  46.199 -            if ( rx_fns[(i * 32) + j] == NULL )
  46.200 -                ring[ring_prod++] = (u16)(((i * 32) + j) | PORT_DISCONNECT);
  46.201 +            ring[ring_prod++] = (u16)(((i * 32) + j) | PORT_NORMAL);
  46.202          }
  46.203      }
  46.204  }
  46.205 @@ -326,8 +230,14 @@ static ssize_t evtchn_write(struct file 
  46.206          goto out;
  46.207      }
  46.208  
  46.209 +    spin_lock_irq(&lock);
  46.210      for ( i = 0; i < (count/2); i++ )
  46.211 -        evtchn_clear_port(kbuf[i]);
  46.212 +    {
  46.213 +        clear_bit(kbuf[i]&PORTIDX_MASK, 
  46.214 +                  (kbuf[i]&PORT_EXCEPTION) ? &pend_exc[0] : &pend_nrm[0]);
  46.215 +        unmask_evtchn(kbuf[i]&PORTIDX_MASK);
  46.216 +    }
  46.217 +    spin_unlock_irq(&lock);
  46.218  
  46.219      rc = count;
  46.220  
  46.221 @@ -455,25 +365,13 @@ static int __init init_module(void)
  46.222      /* (DEVFS) automatically destroy the symlink with its destination. */
  46.223      devfs_auto_unregister(evtchn_miscdev.devfs_handle, symlink_handle);
  46.224  
  46.225 -    err = request_irq(HYPEREVENT_IRQ(_EVENT_EVTCHN),
  46.226 -                      evtchn_interrupt, 0, "evtchn", NULL);
  46.227 -    if ( err != 0 )
  46.228 -    {
  46.229 -        printk(KERN_ALERT "Could not allocate evtchn receive interrupt\n");
  46.230 -        return err;
  46.231 -    }
  46.232 -
  46.233 -    /* Kickstart servicing of notifications. */
  46.234 -    evtchn_interrupt(0, NULL, NULL);
  46.235 -
  46.236 -    printk("Event-channel driver installed.\n");
  46.237 +    printk("Event-channel device installed.\n");
  46.238  
  46.239      return 0;
  46.240  }
  46.241  
  46.242  static void cleanup_module(void)
  46.243  {
  46.244 -    free_irq(HYPEREVENT_IRQ(_EVENT_EVTCHN), NULL);
  46.245      misc_deregister(&evtchn_miscdev);
  46.246  }
  46.247  
    47.1 --- a/xenolinux-2.4.25-sparse/arch/xen/drivers/network/network.c	Wed Mar 24 19:05:53 2004 +0000
    47.2 +++ b/xenolinux-2.4.25-sparse/arch/xen/drivers/network/network.c	Thu Mar 25 15:02:26 2004 +0000
    47.3 @@ -32,6 +32,9 @@ static void network_tx_buf_gc(struct net
    47.4  static void network_alloc_rx_buffers(struct net_device *dev);
    47.5  static void cleanup_module(void);
    47.6  
    47.7 +/* Dynamically-mapped IRQs. */
    47.8 +static int network_irq, debug_irq;
    47.9 +
   47.10  static struct list_head dev_list;
   47.11  
   47.12  struct net_private
   47.13 @@ -545,7 +548,10 @@ static int __init init_module(void)
   47.14      if ( start_info.flags & SIF_INITDOMAIN )
   47.15          (void)register_inetaddr_notifier(&notifier_inetdev);
   47.16  
   47.17 -    err = request_irq(HYPEREVENT_IRQ(_EVENT_NET), network_interrupt, 
   47.18 +    network_irq = bind_virq_to_irq(VIRQ_NET);
   47.19 +    debug_irq   = bind_virq_to_irq(VIRQ_DEBUG);
   47.20 +
   47.21 +    err = request_irq(network_irq, network_interrupt, 
   47.22                        SA_SAMPLE_RANDOM, "network", NULL);
   47.23      if ( err )
   47.24      {
   47.25 @@ -553,7 +559,7 @@ static int __init init_module(void)
   47.26          goto fail;
   47.27      }
   47.28      
   47.29 -    err = request_irq(HYPEREVENT_IRQ(_EVENT_DEBUG), dbg_network_int, 
   47.30 +    err = request_irq(debug_irq, dbg_network_int, 
   47.31                        SA_SHIRQ, "net_dbg", &dbg_network_int);
   47.32      if ( err )
   47.33          printk(KERN_WARNING "Non-fatal error -- no debug interrupt\n");
   47.34 @@ -624,6 +630,12 @@ static void cleanup_module(void)
   47.35  
   47.36      if ( start_info.flags & SIF_INITDOMAIN )
   47.37          (void)unregister_inetaddr_notifier(&notifier_inetdev);
   47.38 +
   47.39 +    free_irq(network_irq, NULL);
   47.40 +    free_irq(debug_irq, NULL);
   47.41 +
   47.42 +    unbind_virq_from_irq(VIRQ_NET);
   47.43 +    unbind_virq_from_irq(VIRQ_DEBUG);
   47.44  }
   47.45  
   47.46  
    48.1 --- a/xenolinux-2.4.25-sparse/arch/xen/drivers/vnetif/vnetif.c	Wed Mar 24 19:05:53 2004 +0000
    48.2 +++ b/xenolinux-2.4.25-sparse/arch/xen/drivers/vnetif/vnetif.c	Thu Mar 25 15:02:26 2004 +0000
    48.3 @@ -32,6 +32,9 @@ static void network_tx_buf_gc(struct net
    48.4  static void network_alloc_rx_buffers(struct net_device *dev);
    48.5  static void cleanup_module(void);
    48.6  
    48.7 +/* Dynamically-mapped IRQs. */
    48.8 +static int network_irq, debug_irq;
    48.9 +
   48.10  static struct list_head dev_list;
   48.11  
   48.12  struct net_private
   48.13 @@ -468,7 +471,10 @@ static int __init init_module(void)
   48.14  
   48.15      INIT_LIST_HEAD(&dev_list);
   48.16  
   48.17 -    err = request_irq(HYPEREVENT_IRQ(_EVENT_NET), network_interrupt, 
   48.18 +    network_irq = bind_virq_to_irq(VIRQ_NET);
   48.19 +    debug_irq   = bind_virq_to_irq(VIRQ_DEBUG);
   48.20 +
   48.21 +    err = request_irq(network_irq, network_interrupt, 
   48.22                        SA_SAMPLE_RANDOM, "network", NULL);
   48.23      if ( err )
   48.24      {
   48.25 @@ -476,7 +482,7 @@ static int __init init_module(void)
   48.26          goto fail;
   48.27      }
   48.28      
   48.29 -    err = request_irq(HYPEREVENT_IRQ(_EVENT_DEBUG), dbg_network_int, 
   48.30 +    err = request_irq(debug_irq, dbg_network_int, 
   48.31                        SA_SHIRQ, "net_dbg", &dbg_network_int);
   48.32      if ( err )
   48.33          printk(KERN_WARNING "Non-fatal error -- no debug interrupt\n");
   48.34 @@ -546,6 +552,12 @@ static void cleanup_module(void)
   48.35          unregister_netdev(dev);
   48.36          kfree(dev);
   48.37      }
   48.38 +
   48.39 +    free_irq(network_irq, NULL);
   48.40 +    free_irq(debug_irq, NULL);
   48.41 +
   48.42 +    unbind_virq_from_irq(VIRQ_NET);
   48.43 +    unbind_virq_from_irq(VIRQ_DEBUG);
   48.44  }
   48.45  
   48.46  
    49.1 --- a/xenolinux-2.4.25-sparse/arch/xen/kernel/Makefile	Wed Mar 24 19:05:53 2004 +0000
    49.2 +++ b/xenolinux-2.4.25-sparse/arch/xen/kernel/Makefile	Thu Mar 25 15:02:26 2004 +0000
    49.3 @@ -10,7 +10,7 @@ export-objs     := i386_ksyms.o
    49.4  
    49.5  obj-y	:= process.o semaphore.o signal.o entry.o traps.o irq.o  \
    49.6  		ptrace.o ioport.o ldt.o setup.o time.o sys_i386.o \
    49.7 -		i386_ksyms.o i387.o hypervisor.o physirq.o pci-dma.o
    49.8 +		i386_ksyms.o i387.o evtchn.o physirq.o pci-dma.o
    49.9  
   49.10  ifdef CONFIG_PCI
   49.11  obj-y	+= pci-i386.o pci-pc.o pci-irq.o
    50.1 --- a/xenolinux-2.4.25-sparse/arch/xen/kernel/entry.S	Wed Mar 24 19:05:53 2004 +0000
    50.2 +++ b/xenolinux-2.4.25-sparse/arch/xen/kernel/entry.S	Thu Mar 25 15:02:26 2004 +0000
    50.3 @@ -68,9 +68,7 @@ IF_MASK		= 0x00000200
    50.4  DF_MASK		= 0x00000400
    50.5  NT_MASK		= 0x00004000
    50.6  
    50.7 -/*
    50.8 - * these are offsets into the task-struct.
    50.9 - */
   50.10 +/* Offsets into task_struct. */
   50.11  state		=  0
   50.12  flags		=  4
   50.13  sigpending	=  8
   50.14 @@ -80,6 +78,10 @@ need_resched	= 20
   50.15  tsk_ptrace	= 24
   50.16  processor	= 52
   50.17  
   50.18 +/* Offsets into shared_info_t. */
   50.19 +#define evtchn_upcall_pending /* 0 */
   50.20 +#define evtchn_upcall_mask       4
   50.21 +
   50.22  ENOSYS = 38
   50.23  
   50.24  
   50.25 @@ -208,14 +210,14 @@ ENTRY(system_call)
   50.26  	movl %eax,EAX(%esp)		# save the return value
   50.27  ENTRY(ret_from_sys_call)
   50.28          movl SYMBOL_NAME(HYPERVISOR_shared_info),%esi
   50.29 -        btrl $EVENTS_MASTER_ENABLE_BIT,4(%esi) # make tests atomic
   50.30 +        btsl $0,evtchn_upcall_mask(%esi) # make tests atomic
   50.31  ret_syscall_tests:
   50.32  	cmpl $0,need_resched(%ebx)
   50.33  	jne reschedule
   50.34  	cmpl $0,sigpending(%ebx)
   50.35  	je   safesti                    # ensure need_resched updates are seen
   50.36  signal_return:
   50.37 -	btsl $EVENTS_MASTER_ENABLE_BIT,4(%esi) # reenable event callbacks
   50.38 +	btrl $0,evtchn_upcall_mask(%esi) # reenable event callbacks
   50.39  	movl %esp,%eax
   50.40  	xorl %edx,%edx
   50.41  	call SYMBOL_NAME(do_signal)
   50.42 @@ -252,7 +254,7 @@ ret_from_exception:
   50.43  
   50.44  	ALIGN
   50.45  reschedule:
   50.46 -        btsl $EVENTS_MASTER_ENABLE_BIT,4(%esi) # reenable event callbacks
   50.47 +        btrl $0,evtchn_upcall_mask(%esi)       # reenable event callbacks
   50.48  	call SYMBOL_NAME(schedule)             # test
   50.49  	jmp ret_from_sys_call
   50.50  
   50.51 @@ -309,18 +311,18 @@ ENTRY(hypervisor_callback)
   50.52          cmpl $ecrit,%eax
   50.53          jb   critical_region_fixup
   50.54  11:     push %esp
   50.55 -        call do_hypervisor_callback
   50.56 +        call evtchn_do_upcall
   50.57          add  $4,%esp
   50.58          movl SYMBOL_NAME(HYPERVISOR_shared_info),%esi
   50.59          movb CS(%esp),%cl
   50.60  	test $2,%cl          # slow return to ring 2 or 3
   50.61  	jne  ret_syscall_tests
   50.62 -safesti:btsl $EVENTS_MASTER_ENABLE_BIT,4(%esi) # reenable event callbacks
   50.63 +safesti:btrl $0,evtchn_upcall_mask(%esi) # reenable event callbacks
   50.64  scrit:  /**** START OF CRITICAL REGION ****/
   50.65 -        cmpl $0,(%esi)
   50.66 -        jne  14f              # process more events if necessary...
   50.67 +        testb $1,evtchn_upcall_pending(%esi)
   50.68 +        jnz  14f              # process more events if necessary...
   50.69          RESTORE_ALL
   50.70 -14:     btrl $EVENTS_MASTER_ENABLE_BIT,4(%esi)
   50.71 +14:     btsl $0,evtchn_upcall_mask(%esi)
   50.72          jmp  11b
   50.73  ecrit:  /**** END OF CRITICAL REGION ****/
   50.74  # [How we do the fixup]. We want to merge the current stack frame with the
   50.75 @@ -349,8 +351,8 @@ 16:     movl %edi,%esp        # final %e
   50.76          jmp  11b
   50.77          
   50.78  critical_fixup_table:        
   50.79 -        .byte 0x00,0x00,0x00                  # cmpl $0,(%esi)
   50.80 -        .byte 0x00,0x00                       # jne  14f
   50.81 +        .byte 0x00,0x00,0x00                  # testb $1,(%esi)
   50.82 +        .byte 0x00,0x00                       # jnz  14f
   50.83          .byte 0x00                            # pop  %ebx
   50.84          .byte 0x04                            # pop  %ecx
   50.85          .byte 0x08                            # pop  %edx
   50.86 @@ -362,7 +364,7 @@ critical_fixup_table:
   50.87          .byte 0x20                            # pop  %es
   50.88          .byte 0x24,0x24,0x24                  # add  $4,%esp
   50.89          .byte 0x28                            # iret
   50.90 -        .byte 0x00,0x00,0x00,0x00,0x00        # btrl $31,4(%esi)
   50.91 +        .byte 0x00,0x00,0x00,0x00,0x00        # btsl $0,4(%esi)
   50.92          .byte 0x00,0x00                       # jmp  11b
   50.93  
   50.94  # Hypervisor uses this for application faults while it executes.
    51.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    51.2 +++ b/xenolinux-2.4.25-sparse/arch/xen/kernel/evtchn.c	Thu Mar 25 15:02:26 2004 +0000
    51.3 @@ -0,0 +1,317 @@
    51.4 +/******************************************************************************
    51.5 + * evtchn.c
    51.6 + * 
    51.7 + * Communication via Xen event channels.
    51.8 + * 
    51.9 + * Copyright (c) 2002-2004, K A Fraser
   51.10 + */
   51.11 +
   51.12 +#include <linux/config.h>
   51.13 +#include <linux/irq.h>
   51.14 +#include <linux/interrupt.h>
   51.15 +#include <linux/sched.h>
   51.16 +#include <linux/kernel_stat.h>
   51.17 +#include <asm/atomic.h>
   51.18 +#include <asm/system.h>
   51.19 +#include <asm/ptrace.h>
   51.20 +#include <asm/hypervisor.h>
   51.21 +#include <asm/hypervisor-ifs/event_channel.h>
   51.22 +
   51.23 +/* Dynamic IRQ <-> event-channel mappings. */
   51.24 +static int evtchn_to_dynirq[1024];
   51.25 +static int dynirq_to_evtchn[NR_IRQS];
   51.26 +
   51.27 +/* Dynamic IRQ <-> VIRQ mapping. */
   51.28 +static int virq_to_dynirq[NR_VIRQS];
   51.29 +
   51.30 +/*
   51.31 + * Reference counts for bindings to dynamic IRQs.
   51.32 + * NB. This array is referenced with respect to DYNIRQ_BASE!
   51.33 + */
   51.34 +static int dynirq_bindcount[NR_DYNIRQS];
   51.35 +static spinlock_t dynirq_lock;
   51.36 +
   51.37 +/* Upcall to generic IRQ layer. */
   51.38 +extern asmlinkage unsigned int do_IRQ(int irq, struct pt_regs *regs);
   51.39 +
   51.40 +static void evtchn_handle_normal(shared_info_t *s, struct pt_regs *regs)
   51.41 +{
   51.42 +    unsigned long l1, l2;
   51.43 +    unsigned int  l1i, l2i, port;
   51.44 +    int           dynirq;
   51.45 +
   51.46 +    l1 = xchg(&s->evtchn_pending_sel, 0);
   51.47 +    while ( (l1i = ffs(l1)) != 0 )
   51.48 +    {
   51.49 +        l1i--;
   51.50 +        l1 &= ~(1 << l1i);
   51.51 +        
   51.52 +        l2 = s->evtchn_pending[l1i] & ~s->evtchn_mask[l1i];
   51.53 +        while ( (l2i = ffs(l2)) != 0 )
   51.54 +        {
   51.55 +            l2i--;
   51.56 +            l2 &= ~(1 << l2i);
   51.57 +            
   51.58 +            port = (l1i << 5) + l2i;
   51.59 +            if ( (dynirq = evtchn_to_dynirq[port]) != -1 )
   51.60 +                do_IRQ(dynirq + DYNIRQ_BASE, regs);
   51.61 +            else
   51.62 +                evtchn_device_upcall(port, 0);
   51.63 +        }
   51.64 +    }
   51.65 +}
   51.66 +
   51.67 +static void evtchn_handle_exceptions(shared_info_t *s, struct pt_regs *regs)
   51.68 +{
   51.69 +    unsigned long l1, l2;
   51.70 +    unsigned int  l1i, l2i, port;
   51.71 +    int           dynirq;
   51.72 +
   51.73 +    l1 = xchg(&s->evtchn_exception_sel, 0);
   51.74 +    while ( (l1i = ffs(l1)) != 0 )
   51.75 +    {
   51.76 +        l1i--;
   51.77 +        l1 &= ~(1 << l1i);
   51.78 +        
   51.79 +        l2 = s->evtchn_exception[l1i] & ~s->evtchn_mask[l1i];
   51.80 +        while ( (l2i = ffs(l2)) != 0 )
   51.81 +        {
   51.82 +            l2i--;
   51.83 +            l2 &= ~(1 << l2i);
   51.84 +            
   51.85 +            port = (l1i << 5) + l2i;
   51.86 +            if ( (dynirq = evtchn_to_dynirq[port]) != -1 )
   51.87 +            {
   51.88 +                printk(KERN_ALERT "Error on IRQ line %d!\n", 
   51.89 +                       dynirq + DYNIRQ_BASE);
   51.90 +                clear_bit(port, &s->evtchn_exception[0]);
   51.91 +            }
   51.92 +            else
   51.93 +                evtchn_device_upcall(port, 1);
   51.94 +        }
   51.95 +    }
   51.96 +}
   51.97 +
   51.98 +void evtchn_do_upcall(struct pt_regs *regs)
   51.99 +{
  51.100 +    unsigned long flags;
  51.101 +    shared_info_t *s = HYPERVISOR_shared_info;
  51.102 +
  51.103 +    local_irq_save(flags);
  51.104 +    
  51.105 +    while ( test_and_clear_bit(0, &s->evtchn_upcall_pending) )
  51.106 +    {
  51.107 +        if ( s->evtchn_pending_sel != 0 )
  51.108 +            evtchn_handle_normal(s, regs);
  51.109 +        if ( s->evtchn_exception_sel != 0 )
  51.110 +            evtchn_handle_exceptions(s, regs);
  51.111 +    }
  51.112 +
  51.113 +    local_irq_restore(flags);
  51.114 +}
  51.115 +
  51.116 +
  51.117 +static int find_unbound_dynirq(void)
  51.118 +{
  51.119 +    int i;
  51.120 +
  51.121 +    for ( i = 0; i < NR_DYNIRQS; i++ )
  51.122 +        if ( dynirq_bindcount[i] == 0 )
  51.123 +            break;
  51.124 +
  51.125 +    if ( i == NR_DYNIRQS )
  51.126 +        BUG();
  51.127 +
  51.128 +    return i;
  51.129 +}
  51.130 +
  51.131 +int bind_virq_to_irq(int virq)
  51.132 +{
  51.133 +    evtchn_op_t op;
  51.134 +    int evtchn, dynirq;
  51.135 +
  51.136 +    spin_lock(&dynirq_lock);
  51.137 +
  51.138 +    if ( (dynirq = virq_to_dynirq[virq]) == -1 )
  51.139 +    {
  51.140 +        op.cmd              = EVTCHNOP_bind_virq;
  51.141 +        op.u.bind_virq.virq = virq;
  51.142 +        if ( HYPERVISOR_event_channel_op(&op) != 0 )
  51.143 +            BUG();
  51.144 +        evtchn = op.u.bind_virq.port;
  51.145 +
  51.146 +        dynirq = find_unbound_dynirq();
  51.147 +        evtchn_to_dynirq[evtchn] = dynirq;
  51.148 +        dynirq_to_evtchn[dynirq] = evtchn;
  51.149 +
  51.150 +        virq_to_dynirq[virq] = dynirq;
  51.151 +    }
  51.152 +
  51.153 +    dynirq_bindcount[dynirq]++;
  51.154 +
  51.155 +    spin_unlock(&dynirq_lock);
  51.156 +    
  51.157 +    return dynirq + DYNIRQ_BASE;
  51.158 +}
  51.159 +
  51.160 +void unbind_virq_from_irq(int virq)
  51.161 +{
  51.162 +    evtchn_op_t op;
  51.163 +    int dynirq = virq_to_dynirq[virq];
  51.164 +    int evtchn = dynirq_to_evtchn[dynirq];
  51.165 +
  51.166 +    spin_lock(&dynirq_lock);
  51.167 +
  51.168 +    if ( --dynirq_bindcount[dynirq] == 0 )
  51.169 +    {
  51.170 +        op.cmd          = EVTCHNOP_close;
  51.171 +        op.u.close.dom  = DOMID_SELF;
  51.172 +        op.u.close.port = evtchn;
  51.173 +        if ( HYPERVISOR_event_channel_op(&op) != 0 )
  51.174 +            BUG();
  51.175 +
  51.176 +        evtchn_to_dynirq[evtchn] = -1;
  51.177 +        dynirq_to_evtchn[dynirq] = -1;
  51.178 +        virq_to_dynirq[virq]     = -1;
  51.179 +    }
  51.180 +
  51.181 +    spin_unlock(&dynirq_lock);
  51.182 +}
  51.183 +
  51.184 +int bind_evtchn_to_irq(int evtchn)
  51.185 +{
  51.186 +    int dynirq;
  51.187 +
  51.188 +    spin_lock(&dynirq_lock);
  51.189 +
  51.190 +    if ( (dynirq = evtchn_to_dynirq[evtchn]) == -1 )
  51.191 +    {
  51.192 +        dynirq = find_unbound_dynirq();
  51.193 +        evtchn_to_dynirq[evtchn] = dynirq;
  51.194 +        dynirq_to_evtchn[dynirq] = evtchn;
  51.195 +    }
  51.196 +
  51.197 +    dynirq_bindcount[dynirq]++;
  51.198 +
  51.199 +    spin_unlock(&dynirq_lock);
  51.200 +    
  51.201 +    return dynirq + DYNIRQ_BASE;
  51.202 +}
  51.203 +
  51.204 +void unbind_evtchn_from_irq(int evtchn)
  51.205 +{
  51.206 +    int dynirq = evtchn_to_dynirq[evtchn];
  51.207 +
  51.208 +    spin_lock(&dynirq_lock);
  51.209 +
  51.210 +    if ( --dynirq_bindcount[dynirq] == 0 )
  51.211 +    {
  51.212 +        evtchn_to_dynirq[evtchn] = -1;
  51.213 +        dynirq_to_evtchn[dynirq] = -1;
  51.214 +    }
  51.215 +
  51.216 +    spin_unlock(&dynirq_lock);
  51.217 +}
  51.218 +
  51.219 +
  51.220 +/*
  51.221 + * Interface to generic handling in irq.c
  51.222 + */
  51.223 +
  51.224 +static unsigned int startup_dynirq(unsigned int irq)
  51.225 +{
  51.226 +    int dynirq = irq - DYNIRQ_BASE;
  51.227 +    unmask_evtchn(dynirq_to_evtchn[dynirq]);
  51.228 +    return 0;
  51.229 +}
  51.230 +
  51.231 +static void shutdown_dynirq(unsigned int irq)
  51.232 +{
  51.233 +    int dynirq = irq - DYNIRQ_BASE;
  51.234 +    mask_evtchn(dynirq_to_evtchn[dynirq]);
  51.235 +}
  51.236 +
  51.237 +static void enable_dynirq(unsigned int irq)
  51.238 +{
  51.239 +    int dynirq = irq - DYNIRQ_BASE;
  51.240 +    unmask_evtchn(dynirq_to_evtchn[dynirq]);
  51.241 +}
  51.242 +
  51.243 +static void disable_dynirq(unsigned int irq)
  51.244 +{
  51.245 +    int dynirq = irq - DYNIRQ_BASE;
  51.246 +    mask_evtchn(dynirq_to_evtchn[dynirq]);
  51.247 +}
  51.248 +
  51.249 +static void ack_dynirq(unsigned int irq)
  51.250 +{
  51.251 +    int dynirq = irq - DYNIRQ_BASE;
  51.252 +    mask_evtchn(dynirq_to_evtchn[dynirq]);
  51.253 +    clear_evtchn(dynirq_to_evtchn[dynirq]);
  51.254 +}
  51.255 +
  51.256 +static void end_dynirq(unsigned int irq)
  51.257 +{
  51.258 +    int dynirq = irq - DYNIRQ_BASE;
  51.259 +    if ( !(irq_desc[irq].status & IRQ_DISABLED) )
  51.260 +        unmask_evtchn(dynirq_to_evtchn[dynirq]);
  51.261 +}
  51.262 +
  51.263 +static struct hw_interrupt_type dynirq_type = {
  51.264 +    "Dynamic-irq",
  51.265 +    startup_dynirq,
  51.266 +    shutdown_dynirq,
  51.267 +    enable_dynirq,
  51.268 +    disable_dynirq,
  51.269 +    ack_dynirq,
  51.270 +    end_dynirq,
  51.271 +    NULL
  51.272 +};
  51.273 +
  51.274 +static void error_interrupt(int irq, void *dev_id, struct pt_regs *regs)
  51.275 +{
  51.276 +    printk(KERN_ALERT "unexpected VIRQ_ERROR trap to vector %d\n", irq);
  51.277 +}
  51.278 +
  51.279 +static struct irqaction error_action = {
  51.280 +    error_interrupt, 
  51.281 +    SA_INTERRUPT, 
  51.282 +    0, 
  51.283 +    "error", 
  51.284 +    NULL, 
  51.285 +    NULL
  51.286 +};
  51.287 +
  51.288 +void __init init_IRQ(void)
  51.289 +{
  51.290 +    int i;
  51.291 +
  51.292 +    for ( i = 0; i < NR_VIRQS; i++ )
  51.293 +        virq_to_dynirq[i] = -1;
  51.294 +
  51.295 +    for ( i = 0; i < 1024; i++ )
  51.296 +        evtchn_to_dynirq[i] = -1;
  51.297 +
  51.298 +    for ( i = 0; i < NR_DYNIRQS; i++ )
  51.299 +    {
  51.300 +        dynirq_to_evtchn[i] = -1;
  51.301 +        dynirq_bindcount[i] = 0;
  51.302 +    }
  51.303 +
  51.304 +    spin_lock_init(&dynirq_lock);
  51.305 +
  51.306 +    for ( i = 0; i < NR_DYNIRQS; i++ )
  51.307 +    {
  51.308 +        irq_desc[i + DYNIRQ_BASE].status  = IRQ_DISABLED;
  51.309 +        irq_desc[i + DYNIRQ_BASE].action  = 0;
  51.310 +        irq_desc[i + DYNIRQ_BASE].depth   = 1;
  51.311 +        irq_desc[i + DYNIRQ_BASE].handler = &dynirq_type;
  51.312 +    }
  51.313 +
  51.314 +    (void)setup_irq(bind_virq_to_irq(VIRQ_ERROR), &error_action);
  51.315 +    
  51.316 +#ifdef CONFIG_PCI
  51.317 +    /* Also initialise the physical IRQ handlers. */
  51.318 +    physirq_init();
  51.319 +#endif
  51.320 +}
    52.1 --- a/xenolinux-2.4.25-sparse/arch/xen/kernel/hypervisor.c	Wed Mar 24 19:05:53 2004 +0000
    52.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    52.3 @@ -1,170 +0,0 @@
    52.4 -/******************************************************************************
    52.5 - * hypervisor.c
    52.6 - * 
    52.7 - * Communication to/from hypervisor.
    52.8 - * 
    52.9 - * Copyright (c) 2002, K A Fraser
   52.10 - */
   52.11 -
   52.12 -#include <linux/config.h>
   52.13 -#include <linux/irq.h>
   52.14 -#include <linux/kernel_stat.h>
   52.15 -#include <asm/atomic.h>
   52.16 -#include <asm/hypervisor.h>
   52.17 -#include <asm/system.h>
   52.18 -#include <asm/ptrace.h>
   52.19 -
   52.20 -multicall_entry_t multicall_list[8];
   52.21 -int nr_multicall_ents = 0;
   52.22 -
   52.23 -static unsigned long event_mask = 0;
   52.24 -
   52.25 -asmlinkage unsigned int do_physirq(int irq, struct pt_regs *regs)
   52.26 -{
   52.27 -    int cpu = smp_processor_id();
   52.28 -    unsigned long irqs;
   52.29 -    shared_info_t *shared = HYPERVISOR_shared_info;
   52.30 -
   52.31 -    /* do this manually */
   52.32 -    kstat.irqs[cpu][irq]++;
   52.33 -    ack_hypervisor_event(irq);
   52.34 -
   52.35 -    barrier();
   52.36 -    irqs  = xchg(&shared->physirq_pend, 0);
   52.37 -
   52.38 -    __asm__ __volatile__ (
   52.39 -        "   push %1                            ;"
   52.40 -        "   sub  $4,%%esp                      ;"
   52.41 -        "   jmp  3f                            ;"
   52.42 -        "1: btrl %%eax,%0                      ;" /* clear bit     */
   52.43 -        "   mov  %%eax,(%%esp)                 ;"
   52.44 -        "   call do_IRQ                        ;" /* do_IRQ(event) */
   52.45 -        "3: bsfl %0,%%eax                      ;" /* %eax == bit # */
   52.46 -        "   jnz  1b                            ;"
   52.47 -        "   add  $8,%%esp                      ;"
   52.48 -        /* we use %ebx because it is callee-saved */
   52.49 -        : : "b" (irqs), "r" (regs)
   52.50 -        /* clobbered by callback function calls */
   52.51 -        : "eax", "ecx", "edx", "memory" ); 
   52.52 -
   52.53 -    /* do this manually */
   52.54 -    end_hypervisor_event(irq);
   52.55 -
   52.56 -    return 0;
   52.57 -}
   52.58 -
   52.59 -void do_hypervisor_callback(struct pt_regs *regs)
   52.60 -{
   52.61 -    unsigned long events, flags;
   52.62 -    shared_info_t *shared = HYPERVISOR_shared_info;
   52.63 -
   52.64 -    do {
   52.65 -        /* Specialised local_irq_save(). */
   52.66 -        flags = test_and_clear_bit(EVENTS_MASTER_ENABLE_BIT, 
   52.67 -                                   &shared->events_mask);
   52.68 -        barrier();
   52.69 -
   52.70 -        events  = xchg(&shared->events, 0);
   52.71 -        events &= event_mask;
   52.72 -
   52.73 -        if ( (events & EVENT_PHYSIRQ) != 0 )
   52.74 -        {
   52.75 -            do_physirq(_EVENT_PHYSIRQ, regs);
   52.76 -            events &= ~EVENT_PHYSIRQ;
   52.77 -        }
   52.78 -
   52.79 -        __asm__ __volatile__ (
   52.80 -            "   push %1                            ;"
   52.81 -            "   sub  $4,%%esp                      ;"
   52.82 -            "   jmp  2f                            ;"
   52.83 -            "1: btrl %%eax,%0                      ;" /* clear bit     */
   52.84 -            "   add  %2,%%eax                      ;"
   52.85 -            "   mov  %%eax,(%%esp)                 ;"
   52.86 -            "   call do_IRQ                        ;" /* do_IRQ(event) */
   52.87 -            "2: bsfl %0,%%eax                      ;" /* %eax == bit # */
   52.88 -            "   jnz  1b                            ;"
   52.89 -            "   add  $8,%%esp                      ;"
   52.90 -            /* we use %ebx because it is callee-saved */
   52.91 -            : : "b" (events), "r" (regs), "i" (HYPEREVENT_IRQ_BASE)
   52.92 -            /* clobbered by callback function calls */
   52.93 -            : "eax", "ecx", "edx", "memory" ); 
   52.94 -
   52.95 -        /* Specialised local_irq_restore(). */
   52.96 -        if ( flags ) set_bit(EVENTS_MASTER_ENABLE_BIT, &shared->events_mask);
   52.97 -        barrier();
   52.98 -    }
   52.99 -    while ( shared->events );
  52.100 -}
  52.101 -
  52.102 -/*
  52.103 - * Define interface to generic handling in irq.c
  52.104 - */
  52.105 -
  52.106 -static void shutdown_hypervisor_event(unsigned int irq)
  52.107 -{
  52.108 -    clear_bit(HYPEREVENT_FROM_IRQ(irq), &event_mask);
  52.109 -    clear_bit(HYPEREVENT_FROM_IRQ(irq), &HYPERVISOR_shared_info->events_mask);
  52.110 -}
  52.111 -
  52.112 -static void enable_hypervisor_event(unsigned int irq)
  52.113 -{
  52.114 -    set_bit(HYPEREVENT_FROM_IRQ(irq), &event_mask);
  52.115 -    set_bit(HYPEREVENT_FROM_IRQ(irq), &HYPERVISOR_shared_info->events_mask);
  52.116 -    if ( test_bit(EVENTS_MASTER_ENABLE_BIT,
  52.117 -                  &HYPERVISOR_shared_info->events_mask) )
  52.118 -        do_hypervisor_callback(NULL);
  52.119 -}
  52.120 -
  52.121 -static void disable_hypervisor_event(unsigned int irq)
  52.122 -{
  52.123 -    clear_bit(HYPEREVENT_FROM_IRQ(irq), &event_mask);
  52.124 -    clear_bit(HYPEREVENT_FROM_IRQ(irq), &HYPERVISOR_shared_info->events_mask);
  52.125 -}
  52.126 -
  52.127 -static void ack_hypervisor_event(unsigned int irq)
  52.128 -{
  52.129 -    int ev = HYPEREVENT_FROM_IRQ(irq);
  52.130 -    if ( !(event_mask & (1<<ev)) )
  52.131 -    {
  52.132 -        printk("Unexpected hypervisor event %d\n", ev);
  52.133 -        atomic_inc(&irq_err_count);
  52.134 -    }
  52.135 -    set_bit(ev, &HYPERVISOR_shared_info->events_mask);
  52.136 -}
  52.137 -
  52.138 -static unsigned int startup_hypervisor_event(unsigned int irq)
  52.139 -{
  52.140 -    enable_hypervisor_event(irq);
  52.141 -    return 0;
  52.142 -}
  52.143 -
  52.144 -static void end_hypervisor_event(unsigned int irq)
  52.145 -{
  52.146 -}
  52.147 -
  52.148 -static struct hw_interrupt_type hypervisor_irq_type = {
  52.149 -    "Hypervisor-event",
  52.150 -    startup_hypervisor_event,
  52.151 -    shutdown_hypervisor_event,
  52.152 -    enable_hypervisor_event,
  52.153 -    disable_hypervisor_event,
  52.154 -    ack_hypervisor_event,
  52.155 -    end_hypervisor_event,
  52.156 -    NULL
  52.157 -};
  52.158 -
  52.159 -void __init init_IRQ(void)
  52.160 -{
  52.161 -    int i;
  52.162 -
  52.163 -    for ( i = 0; i < NR_HYPEREVENT_IRQS; i++ )
  52.164 -    {
  52.165 -        irq_desc[i + HYPEREVENT_IRQ_BASE].status  = IRQ_DISABLED;
  52.166 -        irq_desc[i + HYPEREVENT_IRQ_BASE].action  = 0;
  52.167 -        irq_desc[i + HYPEREVENT_IRQ_BASE].depth   = 1;
  52.168 -        irq_desc[i + HYPEREVENT_IRQ_BASE].handler = &hypervisor_irq_type;
  52.169 -    }
  52.170 -
  52.171 -    /* Also initialise the physical IRQ handlers. */
  52.172 -    physirq_init();
  52.173 -}
    53.1 --- a/xenolinux-2.4.25-sparse/arch/xen/kernel/i386_ksyms.c	Wed Mar 24 19:05:53 2004 +0000
    53.2 +++ b/xenolinux-2.4.25-sparse/arch/xen/kernel/i386_ksyms.c	Thu Mar 25 15:02:26 2004 +0000
    53.3 @@ -171,5 +171,5 @@ EXPORT_SYMBOL(xquad_portio);
    53.4  EXPORT_SYMBOL(create_xen_proc_entry);
    53.5  EXPORT_SYMBOL(remove_xen_proc_entry);
    53.6  
    53.7 -EXPORT_SYMBOL(do_hypervisor_callback);
    53.8 +EXPORT_SYMBOL(evtchn_do_upcall);
    53.9  EXPORT_SYMBOL(HYPERVISOR_shared_info);
    54.1 --- a/xenolinux-2.4.25-sparse/arch/xen/kernel/physirq.c	Wed Mar 24 19:05:53 2004 +0000
    54.2 +++ b/xenolinux-2.4.25-sparse/arch/xen/kernel/physirq.c	Thu Mar 25 15:02:26 2004 +0000
    54.3 @@ -13,6 +13,7 @@
    54.4   *              by the virq irq type.
    54.5   */
    54.6  
    54.7 +#ifdef CONFIG_PCI
    54.8  
    54.9  #include <linux/config.h>
   54.10  #include <asm/atomic.h>
   54.11 @@ -46,7 +47,7 @@ static unsigned int startup_physirq_even
   54.12      {
   54.13          printk("startup_physirq_event %d: setup event handler\n", irq);
   54.14          /* set up a event handler to demux virtualised physical interrupts */
   54.15 -        err = request_irq(HYPEREVENT_IRQ(_EVENT_PHYSIRQ), physirq_interrupt, 
   54.16 +        err = request_irq(IRQ_FROM_XEN_VIRQ(VIRQ_PHYSIRQ), physirq_interrupt, 
   54.17                            SA_SAMPLE_RANDOM, "physirq", NULL);
   54.18          if ( err )
   54.19          {
   54.20 @@ -106,13 +107,13 @@ static void shutdown_physirq_event(unsig
   54.21  static void enable_physirq_event(unsigned int irq)
   54.22  {
   54.23      /* XXX just enable all phys interrupts for now */
   54.24 -    enable_irq(HYPEREVENT_IRQ(_EVENT_PHYSIRQ));
   54.25 +    enable_irq(IRQ_FROM_XEN_VIRQ(VIRQ_PHYSIRQ));
   54.26  }
   54.27  
   54.28  static void disable_physirq_event(unsigned int irq)
   54.29  {
   54.30      /* XXX just disable all phys interrupts for now */
   54.31 -    disable_irq(HYPEREVENT_IRQ(_EVENT_PHYSIRQ));
   54.32 +    disable_irq(IRQ_FROM_XEN_VIRQ(VIRQ_PHYSIRQ));
   54.33  }
   54.34  
   54.35  static void ack_physirq_event(unsigned int irq)
   54.36 @@ -170,3 +171,5 @@ void __init physirq_init(void)
   54.37          irq_desc[i + PHYS_IRQ_BASE].handler = &physirq_irq_type;
   54.38      }
   54.39  }
   54.40 +
   54.41 +#endif
    55.1 --- a/xenolinux-2.4.25-sparse/arch/xen/kernel/setup.c	Wed Mar 24 19:05:53 2004 +0000
    55.2 +++ b/xenolinux-2.4.25-sparse/arch/xen/kernel/setup.c	Thu Mar 25 15:02:26 2004 +0000
    55.3 @@ -58,6 +58,9 @@ shared_info_t *HYPERVISOR_shared_info = 
    55.4  
    55.5  unsigned long *phys_to_machine_mapping;
    55.6  
    55.7 +multicall_entry_t multicall_list[8];
    55.8 +int nr_multicall_ents = 0;
    55.9 +
   55.10  /*
   55.11   * Machine setup..
   55.12   */
   55.13 @@ -860,7 +863,8 @@ void __init identify_cpu(struct cpuinfo_
   55.14          break;
   55.15          
   55.16      default:
   55.17 -        printk("Unsupported CPU vendor (%d) -- please report!\n");
   55.18 +        printk("Unsupported CPU vendor (%d) -- please report!\n",
   55.19 +               c->x86_vendor);
   55.20      }
   55.21  	
   55.22      printk(KERN_DEBUG "CPU: After vendor init, caps: %08x %08x %08x %08x\n",
   55.23 @@ -1116,7 +1120,10 @@ void __init cpu_init (void)
   55.24   * Time-to-die callback handling.
   55.25   */
   55.26  
   55.27 -static void die_irq(int irq, void *unused, struct pt_regs *regs)
   55.28 +/* Dynamically-mapped IRQ. */
   55.29 +static int die_irq;
   55.30 +
   55.31 +static void die_interrupt(int irq, void *unused, struct pt_regs *regs)
   55.32  {
   55.33      extern void ctrl_alt_del(void);
   55.34      ctrl_alt_del();
   55.35 @@ -1124,7 +1131,8 @@ static void die_irq(int irq, void *unuse
   55.36  
   55.37  static int __init setup_die_event(void)
   55.38  {
   55.39 -    (void)request_irq(HYPEREVENT_IRQ(_EVENT_DIE), die_irq, 0, "die", NULL);
   55.40 +    die_irq = bind_virq_to_irq(VIRQ_DIE);
   55.41 +    (void)request_irq(die_irq, die_interrupt, 0, "die", NULL);
   55.42      return 0;
   55.43  }
   55.44  
   55.45 @@ -1241,7 +1249,10 @@ static void stop_task(void *unused)
   55.46  
   55.47  static struct tq_struct stop_tq;
   55.48  
   55.49 -static void stop_irq(int irq, void *unused, struct pt_regs *regs)
   55.50 +/* Dynamically-mapped IRQ. */
   55.51 +static int stop_irq;
   55.52 +
   55.53 +static void stop_interrupt(int irq, void *unused, struct pt_regs *regs)
   55.54  {
   55.55      stop_tq.routine = stop_task;
   55.56      schedule_task(&stop_tq);
   55.57 @@ -1249,7 +1260,8 @@ static void stop_irq(int irq, void *unus
   55.58  
   55.59  static int __init setup_stop_event(void)
   55.60  {
   55.61 -    (void)request_irq(HYPEREVENT_IRQ(_EVENT_STOP), stop_irq, 0, "stop", NULL);
   55.62 +    stop_irq = bind_virq_to_irq(VIRQ_STOP);
   55.63 +    (void)request_irq(stop_irq, stop_interrupt, 0, "stop", NULL);
   55.64      return 0;
   55.65  }
   55.66  
    56.1 --- a/xenolinux-2.4.25-sparse/arch/xen/kernel/time.c	Wed Mar 24 19:05:53 2004 +0000
    56.2 +++ b/xenolinux-2.4.25-sparse/arch/xen/kernel/time.c	Thu Mar 25 15:02:26 2004 +0000
    56.3 @@ -115,6 +115,8 @@ static u64 processed_system_time;   /* S
    56.4          }                                  \
    56.5      } while ( 0 )
    56.6  
    56.7 +/* Dynamically-mapped IRQs. */
    56.8 +static int time_irq, debug_irq;
    56.9  
   56.10  /* Does this guest OS track Xen time, or set its wall clock independently? */
   56.11  static int independent_wallclock = 0;
   56.12 @@ -623,13 +625,13 @@ void __init time_init(void)
   56.13      __get_time_values_from_xen();
   56.14      processed_system_time = shadow_system_time;
   56.15  
   56.16 -    (void)setup_irq(HYPEREVENT_IRQ(_EVENT_TIMER), &irq_timer);
   56.17 +    time_irq  = bind_virq_to_irq(VIRQ_TIMER);
   56.18 +    debug_irq = bind_virq_to_irq(VIRQ_DEBUG);
   56.19  
   56.20 -    (void)setup_irq(HYPEREVENT_IRQ(_EVENT_DEBUG), &dbg_time);
   56.21 +    (void)setup_irq(time_irq, &irq_timer);
   56.22 +    (void)setup_irq(debug_irq, &dbg_time);
   56.23  
   56.24      rdtscll(alarm);
   56.25 -
   56.26 -    clear_bit(_EVENT_TIMER, &HYPERVISOR_shared_info->events);
   56.27  }
   56.28  
   56.29  
    57.1 --- a/xenolinux-2.4.25-sparse/include/asm-xen/evtchn.h	Wed Mar 24 19:05:53 2004 +0000
    57.2 +++ b/xenolinux-2.4.25-sparse/include/asm-xen/evtchn.h	Thu Mar 25 15:02:26 2004 +0000
    57.3 @@ -1,7 +1,8 @@
    57.4  /******************************************************************************
    57.5   * evtchn.h
    57.6   * 
    57.7 - * Driver for receiving and demuxing event-channel signals.
    57.8 + * Communication via Xen event channels.
    57.9 + * Also definitions for the device that demuxes notifications to userspace.
   57.10   * 
   57.11   * Copyright (c) 2004, K A Fraser
   57.12   */
   57.13 @@ -9,10 +10,81 @@
   57.14  #ifndef __ASM_EVTCHN_H__
   57.15  #define __ASM_EVTCHN_H__
   57.16  
   57.17 -typedef void (*evtchn_receiver_t)(unsigned int);
   57.18 -#define PORT_NORMAL     0x0000
   57.19 -#define PORT_DISCONNECT 0x8000
   57.20 -#define PORTIDX_MASK    0x7fff
   57.21 +#include <linux/config.h>
   57.22 +#include <asm/hypervisor.h>
   57.23 +#include <asm/ptrace.h>
   57.24 +
   57.25 +/*
   57.26 + * LOW-LEVEL DEFINITIONS
   57.27 + */
   57.28 +
   57.29 +/* Entry point for notifications into Linux subsystems. */
   57.30 +void evtchn_do_upcall(struct pt_regs *regs);
   57.31 +
   57.32 +/* Entry point for notifications into the userland character device. */
   57.33 +void evtchn_device_upcall(int port, int exception);
   57.34 +
   57.35 +static inline void mask_evtchn(int port)
   57.36 +{
   57.37 +    shared_info_t *s = HYPERVISOR_shared_info;
   57.38 +    set_bit(port, &s->evtchn_mask[0]);
   57.39 +}
   57.40 +
   57.41 +/*
   57.42 + * I haven't thought too much about the synchronisation in here against
   57.43 + * other CPUs, but all the bit-update operations are reorder barriers on
   57.44 + * x86 so reordering concerns aren't a problem for now. Some mb() calls
   57.45 + * would be required on weaker architectures I think. -- KAF (24/3/2004)
   57.46 + */
   57.47 +static inline void unmask_evtchn(int port)
   57.48 +{
   57.49 +    shared_info_t *s = HYPERVISOR_shared_info;
   57.50 +    int need_upcall = 0;
   57.51 +
   57.52 +    clear_bit(port, &s->evtchn_mask[0]);
   57.53 +
   57.54 +    /*
   57.55 +     * The following is basically the equivalent of 'hw_resend_irq'. Just like
   57.56 +     * a real IO-APIC we 'lose the interrupt edge' if the channel is masked.
   57.57 +     */
   57.58 +
   57.59 +    /* Asserted a standard notification? */
   57.60 +    if (  test_bit        (port,    &s->evtchn_pending[0]) && 
   57.61 +         !test_and_set_bit(port>>5, &s->evtchn_pending_sel) )
   57.62 +        need_upcall = 1;
   57.63 +
   57.64 +    /* Asserted an exceptional notification? */
   57.65 +    if (  test_bit        (port,    &s->evtchn_exception[0]) && 
   57.66 +         !test_and_set_bit(port>>5, &s->evtchn_exception_sel) )
   57.67 +        need_upcall = 1;
   57.68 +
   57.69 +    /* If asserted either type of notification, check the master flags. */
   57.70 +    if ( need_upcall &&
   57.71 +         !test_and_set_bit(0,       &s->evtchn_upcall_pending) &&
   57.72 +         !test_bit        (0,       &s->evtchn_upcall_mask) )
   57.73 +        evtchn_do_upcall(NULL);
   57.74 +}
   57.75 +
   57.76 +static inline void clear_evtchn(int port)
   57.77 +{
   57.78 +    shared_info_t *s = HYPERVISOR_shared_info;
   57.79 +    clear_bit(port, &s->evtchn_pending[0]);
   57.80 +}
   57.81 +
   57.82 +static inline void clear_evtchn_exception(int port)
   57.83 +{
   57.84 +    shared_info_t *s = HYPERVISOR_shared_info;
   57.85 +    clear_bit(port, &s->evtchn_exception[0]);
   57.86 +}
   57.87 +
   57.88 +
   57.89 +/*
   57.90 + * CHARACTER-DEVICE DEFINITIONS
   57.91 + */
   57.92 +
   57.93 +#define PORT_NORMAL    0x0000
   57.94 +#define PORT_EXCEPTION 0x8000
   57.95 +#define PORTIDX_MASK   0x7fff
   57.96  
   57.97  /* /dev/xen/evtchn resides at device number major=10, minor=200 */
   57.98  #define EVTCHN_MINOR 200
   57.99 @@ -21,9 +93,4 @@ typedef void (*evtchn_receiver_t)(unsign
  57.100  /* EVTCHN_RESET: Clear and reinit the event buffer. Clear error condition. */
  57.101  #define EVTCHN_RESET _IO('E', 1)
  57.102  
  57.103 -int evtchn_request_port(unsigned int port, evtchn_receiver_t rx_fn);
  57.104 -int evtchn_free_port(unsigned int port);
  57.105 -void evtchn_clear_port(unsigned int port);
  57.106 -
  57.107 -
  57.108  #endif /* __ASM_EVTCHN_H__ */
    58.1 --- a/xenolinux-2.4.25-sparse/include/asm-xen/hypervisor.h	Wed Mar 24 19:05:53 2004 +0000
    58.2 +++ b/xenolinux-2.4.25-sparse/include/asm-xen/hypervisor.h	Thu Mar 25 15:02:26 2004 +0000
    58.3 @@ -25,10 +25,6 @@ union start_info_union
    58.4  extern union start_info_union start_info_union;
    58.5  #define start_info (start_info_union.start_info)
    58.6  
    58.7 -/* arch/xen/kernel/hypervisor.c */
    58.8 -void do_hypervisor_callback(struct pt_regs *regs);
    58.9 -
   58.10 -
   58.11  /* arch/xen/mm/hypervisor.c */
   58.12  /*
   58.13   * NB. ptr values should be PHYSICAL, not MACHINE. 'vals' should be already
    59.1 --- a/xenolinux-2.4.25-sparse/include/asm-xen/irq.h	Wed Mar 24 19:05:53 2004 +0000
    59.2 +++ b/xenolinux-2.4.25-sparse/include/asm-xen/irq.h	Thu Mar 25 15:02:26 2004 +0000
    59.3 @@ -14,19 +14,32 @@
    59.4  #include <asm/hypervisor.h>
    59.5  #include <asm/ptrace.h>
    59.6  
    59.7 -#define NR_IRQS             256
    59.8 -
    59.9 -#define PHYS_IRQ_BASE         0
   59.10 -#define NR_PHYS_IRQS        128
   59.11 +/*
   59.12 + * The flat IRQ space is divided into two regions:
   59.13 + *  1. A one-to-one mapping of real physical IRQs. This space is only used
   59.14 + *     if we have physical device-access privilege. This region is at the 
   59.15 + *     start of the IRQ space so that existing device drivers do not need
   59.16 + *     to be modified to translate physical IRQ numbers into our IRQ space.
   59.17 + *  3. A dynamic mapping of inter-domain and Xen-sourced virtual IRQs. These
   59.18 + *     are bound using the provided bind/unbind functions.
   59.19 + */
   59.20  
   59.21 -#define HYPEREVENT_IRQ_BASE 128
   59.22 -#define NR_HYPEREVENT_IRQS  128
   59.23 +#define PIRQ_BASE   0
   59.24 +#define NR_PIRQS  128
   59.25  
   59.26 -#define HYPEREVENT_IRQ(_ev)       ((_ev)  + HYPEREVENT_IRQ_BASE)
   59.27 -#define HYPEREVENT_FROM_IRQ(_irq) ((_irq) - HYPEREVENT_IRQ_BASE)
   59.28 +#define DYNIRQ_BASE (PIRQ_BASE + NR_PIRQS)
   59.29 +#define NR_DYNIRQS  128
   59.30 +
   59.31 +#define NR_IRQS   (NR_PIRQS + NR_DYNIRQS)
   59.32  
   59.33  extern void physirq_init(void);
   59.34  
   59.35 +/* Dynamic binding of event channels and VIRQ sources to Linux IRQ space. */
   59.36 +extern int  bind_virq_to_irq(int virq);
   59.37 +extern void unbind_virq_from_irq(int virq);
   59.38 +extern int  bind_evtchn_to_irq(int evtchn);
   59.39 +extern void unbind_evtchn_from_irq(int evtchn);
   59.40 +
   59.41  #define irq_cannonicalize(_irq) (_irq)
   59.42  
   59.43  extern void disable_irq(unsigned int);
    60.1 --- a/xenolinux-2.4.25-sparse/include/asm-xen/keyboard.h	Wed Mar 24 19:05:53 2004 +0000
    60.2 +++ b/xenolinux-2.4.25-sparse/include/asm-xen/keyboard.h	Thu Mar 25 15:02:26 2004 +0000
    60.3 @@ -58,8 +58,11 @@ static inline int xen_kbd_controller_pre
    60.4  /* resource allocation */
    60.5  #define kbd_request_region()     \
    60.6      do { } while (0)
    60.7 -#define kbd_request_irq(handler) \
    60.8 -    request_irq(HYPEREVENT_IRQ(_EVENT_PS2), handler, 0, "ps/2", NULL)
    60.9 +#define kbd_request_irq(handler)                    \
   60.10 +    do {                                            \
   60.11 +        int irq = bind_virq_to_irq(VIRQ_PS2);       \
   60.12 +        request_irq(irq, handler, 0, "ps/2", NULL); \
   60.13 +    } while ( 0 )
   60.14  
   60.15  /* could implement these with command to xen to filter mouse stuff... */
   60.16  #define aux_request_irq(hand, dev_id) 0
    61.1 --- a/xenolinux-2.4.25-sparse/include/asm-xen/system.h	Wed Mar 24 19:05:53 2004 +0000
    61.2 +++ b/xenolinux-2.4.25-sparse/include/asm-xen/system.h	Thu Mar 25 15:02:26 2004 +0000
    61.3 @@ -7,6 +7,7 @@
    61.4  #include <asm/segment.h>
    61.5  #include <asm/hypervisor.h>
    61.6  #include <linux/bitops.h> /* for LOCK_PREFIX */
    61.7 +#include <asm/evtchn.h>
    61.8  
    61.9  #ifdef __KERNEL__
   61.10  
   61.11 @@ -319,29 +320,38 @@ static inline unsigned long __cmpxchg(vo
   61.12  
   61.13  #define set_wmb(var, value) do { var = value; wmb(); } while (0)
   61.14  
   61.15 +/*
   61.16 + * NB. ALl the following routines are SMP-safe on x86, even where they look
   61.17 + * possibly racy. For example, we must ensure that we clear the mask bit and
   61.18 + * /then/ check teh pending bit. But this will happen because the bit-update
   61.19 + * operations are ordering barriers.
   61.20 + * 
   61.21 + * For this reason also, many uses of 'barrier' here are rather anal. But
   61.22 + * they do no harm.
   61.23 + */
   61.24  
   61.25  #define __cli()                                                               \
   61.26  do {                                                                          \
   61.27 -    clear_bit(EVENTS_MASTER_ENABLE_BIT, &HYPERVISOR_shared_info->events_mask);\
   61.28 +    set_bit(0, &HYPERVISOR_shared_info->evtchn_upcall_mask);                  \
   61.29      barrier();                                                                \
   61.30  } while (0)
   61.31  
   61.32  #define __sti()                                                               \
   61.33  do {                                                                          \
   61.34      shared_info_t *_shared = HYPERVISOR_shared_info;                          \
   61.35 -    set_bit(EVENTS_MASTER_ENABLE_BIT, &_shared->events_mask);                 \
   61.36 +    clear_bit(0, &_shared->evtchn_upcall_mask);                               \
   61.37      barrier();                                                                \
   61.38 -    if ( unlikely(_shared->events) ) do_hypervisor_callback(NULL);            \
   61.39 +    if ( unlikely(test_bit(0, &_shared->evtchn_upcall_pending)) )             \
   61.40 +        evtchn_do_upcall(NULL);                                               \
   61.41  } while (0)
   61.42  
   61.43  #define __save_flags(x)                                                       \
   61.44  do {                                                                          \
   61.45 -    (x) = test_bit(EVENTS_MASTER_ENABLE_BIT,                                  \
   61.46 -                   &HYPERVISOR_shared_info->events_mask);                     \
   61.47 +    (x) = test_bit(0, &HYPERVISOR_shared_info->evtchn_upcall_mask);           \
   61.48      barrier();                                                                \
   61.49  } while (0)
   61.50  
   61.51 -#define __restore_flags(x)      do { if (x) __sti(); } while (0)
   61.52 +#define __restore_flags(x)      do { if (x) __cli(); else __sti(); } while (0)
   61.53  
   61.54  #define safe_halt()             ((void)0)
   61.55  
   61.56 @@ -350,8 +360,7 @@ do {                                    
   61.57  
   61.58  #define local_irq_save(x)                                                     \
   61.59  do {                                                                          \
   61.60 -    (x) = test_and_clear_bit(EVENTS_MASTER_ENABLE_BIT,                        \
   61.61 -                             &HYPERVISOR_shared_info->events_mask);           \
   61.62 +    (x) = test_and_set_bit(0, &HYPERVISOR_shared_info->evtchn_upcall_mask);   \
   61.63      barrier();                                                                \
   61.64  } while (0)
   61.65  #define local_irq_restore(x)    __restore_flags(x)