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
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
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, ¤t->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, ¤t->shared_info->events_mask); 25.8 + clear_bit(0, ¤t->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(¤t->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(¤t->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(¤t->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(¤t->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(¤t->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(¬ifier_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(¬ifier_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)