diff options
author | iap10@tetris.cl.cam.ac.uk <iap10@tetris.cl.cam.ac.uk> | 2004-03-25 12:37:30 +0000 |
---|---|---|
committer | iap10@tetris.cl.cam.ac.uk <iap10@tetris.cl.cam.ac.uk> | 2004-03-25 12:37:30 +0000 |
commit | 3edb6b4a07f3b5e8628accd97e20ace4cf8ceb4a (patch) | |
tree | 99339d353e2acc57c74ee7c33d7cc35c65efe4f9 | |
parent | 163ce6261c54cbfe6fec6f011497a3d14d30b5e4 (diff) | |
parent | 1cfe846da9267b5ee87813bb9e44d2a0a8ebaa12 (diff) | |
download | xen-3edb6b4a07f3b5e8628accd97e20ace4cf8ceb4a.tar.gz xen-3edb6b4a07f3b5e8628accd97e20ace4cf8ceb4a.tar.bz2 xen-3edb6b4a07f3b5e8628accd97e20ace4cf8ceb4a.zip |
bitkeeper revision 1.825.2.1 (4062d28avHqOBupTrfJcONXWeibf9A)
grand unification of shadow table stuff
-rw-r--r-- | .rootkeys | 2 | ||||
-rw-r--r-- | BitKeeper/etc/ignore | 558 | ||||
-rw-r--r-- | xen/arch/i386/domain_page.c | 2 | ||||
-rw-r--r-- | xen/arch/i386/process.c | 10 | ||||
-rw-r--r-- | xen/arch/i386/traps.c | 12 | ||||
-rw-r--r-- | xen/common/debug.c | 6 | ||||
-rw-r--r-- | xen/common/domain.c | 19 | ||||
-rw-r--r-- | xen/common/kernel.c | 23 | ||||
-rw-r--r-- | xen/common/memory.c | 117 | ||||
-rw-r--r-- | xen/common/perfc.c | 43 | ||||
-rw-r--r-- | xen/common/shadow.c | 793 | ||||
-rw-r--r-- | xen/include/asm-i386/config.h | 8 | ||||
-rw-r--r-- | xen/include/asm-i386/page.h | 1 | ||||
-rw-r--r-- | xen/include/asm-i386/processor.h | 11 | ||||
-rw-r--r-- | xen/include/xen/mm.h | 1 | ||||
-rw-r--r-- | xen/include/xen/perfc.h | 12 | ||||
-rw-r--r-- | xen/include/xen/perfc_defn.h | 17 | ||||
-rw-r--r-- | xen/include/xeno/shadow.h | 344 | ||||
-rw-r--r-- | xen/net/dev.c | 44 |
19 files changed, 1978 insertions, 45 deletions
@@ -178,6 +178,7 @@ 40589968dD2D1aejwSOvrROg7fOvGQ xen/common/sched_bvt.c 40589968be_t_n0-w6ggceW7h-sx0w xen/common/sched_rrobin.c 3e397e6619PgAfBbw2XFbXkewvUWgw xen/common/schedule.c +405b8599xI_PoEr3zZoJ2on-jdn7iw xen/common/shadow.c 3ddb79bdB9RNMnkQnUyZ5C9hhMSQQw xen/common/slab.c 3ddb79bd0gVQYmL2zvuJnldvD0AGxQ xen/common/softirq.c 3e7f358awXBC3Vw-wFRwPw18qL1khg xen/common/string.c @@ -590,6 +591,7 @@ 3f055a3dwldYR102YcSuBaxIf9t3Jw xen/include/xen/vbd.h 3e8827bdaqPeZAWGVOwswgY9bWSx4g xen/include/xen/version.h 3ddb79c2Ae5KpzhC9LCYG7mP_Vi4Aw xen/include/xen/vif.h +405b8599BsDsDwKEJLS0XipaiQW3TA xen/include/xeno/shadow.h 3ddb79c4YQCQ6r0xNLLu0jfbM7pVmA xen/net/Makefile 3ddb79c4AkfDkTCw0comx4L8wsUOMg xen/net/dev.c 3ddb79c4x1L_soh8b-r_1jQW_37Icw xen/net/dev_mcast.c diff --git a/BitKeeper/etc/ignore b/BitKeeper/etc/ignore index 65b199bec3..33f30c8f3e 100644 --- a/BitKeeper/etc/ignore +++ b/BitKeeper/etc/ignore @@ -1,27 +1,567 @@ -BitKeeper/*/* -PENDING/* +*.a *.o +*.pyc *.so *.so.* -*.a -*.pyc +BitKeeper/*/* +PENDING/* +TAGS +URK extras/mini-os/h/hypervisor-ifs tools/*/build/lib*/*.py tools/balloon/balloon +tools/control/.checkstyle +tools/control/.classpath +tools/control/.project +tools/control/build-cmdline/** +tools/control/build-dom/uk/ac/cam/cl/xeno/domctl/Command.class +tools/control/build-dom/uk/ac/cam/cl/xeno/domctl/CommandDestroy.class +tools/control/build-dom/uk/ac/cam/cl/xeno/domctl/CommandHelp.class +tools/control/build-dom/uk/ac/cam/cl/xeno/domctl/CommandList.class +tools/control/build-dom/uk/ac/cam/cl/xeno/domctl/CommandNew.class +tools/control/build-dom/uk/ac/cam/cl/xeno/domctl/CommandStart.class +tools/control/build-dom/uk/ac/cam/cl/xeno/domctl/CommandStop.class +tools/control/build-dom/uk/ac/cam/cl/xeno/domctl/Defaults$Handler.class +tools/control/build-dom/uk/ac/cam/cl/xeno/domctl/Defaults.class +tools/control/build-dom/uk/ac/cam/cl/xeno/domctl/Domain.class +tools/control/build-dom/uk/ac/cam/cl/xeno/domctl/InetAddressPattern.class +tools/control/build-dom/uk/ac/cam/cl/xeno/domctl/Main.class +tools/control/build-dom/uk/ac/cam/cl/xeno/domctl/Settings.class +tools/control/build-dom/uk/ac/cam/cl/xeno/domctl/StringPattern.class +tools/control/build-web/** +tools/control/build-xen/WEB-INF/classes/uk/ac/cam/cl/xeno/domctl/Command.class +tools/control/build-xen/WEB-INF/classes/uk/ac/cam/cl/xeno/domctl/CommandDestroy.class +tools/control/build-xen/WEB-INF/classes/uk/ac/cam/cl/xeno/domctl/CommandHelp.class +tools/control/build-xen/WEB-INF/classes/uk/ac/cam/cl/xeno/domctl/CommandList.class +tools/control/build-xen/WEB-INF/classes/uk/ac/cam/cl/xeno/domctl/CommandNew.class +tools/control/build-xen/WEB-INF/classes/uk/ac/cam/cl/xeno/domctl/CommandStart.class +tools/control/build-xen/WEB-INF/classes/uk/ac/cam/cl/xeno/domctl/CommandStop.class +tools/control/build-xen/WEB-INF/classes/uk/ac/cam/cl/xeno/domctl/Defaults$Handler.class +tools/control/build-xen/WEB-INF/classes/uk/ac/cam/cl/xeno/domctl/Defaults.class +tools/control/build-xen/WEB-INF/classes/uk/ac/cam/cl/xeno/domctl/Domain.class +tools/control/build-xen/WEB-INF/classes/uk/ac/cam/cl/xeno/domctl/InetAddressPattern.class +tools/control/build-xen/WEB-INF/classes/uk/ac/cam/cl/xeno/domctl/Main.class +tools/control/build-xen/WEB-INF/classes/uk/ac/cam/cl/xeno/domctl/Settings.class +tools/control/build-xen/WEB-INF/classes/uk/ac/cam/cl/xeno/domctl/StringPattern.class +tools/control/build-xen/WEB-INF/classes/uk/ac/cam/cl/xeno/xenctl/Extent.class +tools/control/build-xen/WEB-INF/classes/uk/ac/cam/cl/xeno/xenctl/Library.class +tools/control/build-xen/WEB-INF/classes/uk/ac/cam/cl/xeno/xenctl/Main.java.orig +tools/control/build-xen/WEB-INF/classes/uk/ac/cam/cl/xeno/xenctl/Mode.class +tools/control/build-xen/WEB-INF/classes/uk/ac/cam/cl/xeno/xenctl/Parser.class +tools/control/build-xen/WEB-INF/classes/uk/ac/cam/cl/xeno/xenctl/Partition.class +tools/control/build-xen/WEB-INF/classes/uk/ac/cam/cl/xeno/xenctl/PartitionManager.class +tools/control/build-xen/WEB-INF/classes/uk/ac/cam/cl/xeno/xenctl/RootBean.class +tools/control/build-xen/WEB-INF/classes/uk/ac/cam/cl/xeno/xenctl/SystemConfigurationBean.class +tools/control/build-xen/WEB-INF/classes/uk/ac/cam/cl/xeno/xenctl/VirtualBlockDevice.class +tools/control/build-xen/WEB-INF/classes/uk/ac/cam/cl/xeno/xenctl/VirtualDisk.class +tools/control/build-xen/WEB-INF/classes/uk/ac/cam/cl/xeno/xenctl/VirtualDiskManager.class +tools/control/build-xen/WEB-INF/classes/uk/ac/cam/cl/xeno/xenctl/XML.class +tools/control/build-xen/WEB-INF/classes/uk/ac/cam/cl/xeno/xenctl/XMLHelper.class +tools/control/build-xen/WEB-INF/web.xml +tools/control/build-xen/about.jsp +tools/control/build-xen/dom-del.jsp +tools/control/build-xen/dom-delr.jsp +tools/control/build-xen/dom-lis.jsp +tools/control/build-xen/dom-new.jsp +tools/control/build-xen/dom-newr.jsp +tools/control/build-xen/dom-sta.jsp +tools/control/build-xen/dom-star.jsp +tools/control/build-xen/dom-stp.jsp +tools/control/build-xen/dom-stpr.jsp +tools/control/build-xen/dom.jsp +tools/control/build-xen/help.jsp +tools/control/build-xen/img/cambridge.gif +tools/control/build-xen/img/help.gif +tools/control/build-xen/img/home.gif +tools/control/build-xen/img/pixel.gif +tools/control/build-xen/img/search.gif +tools/control/build-xen/img/xeno.gif +tools/control/build-xen/index.jsp +tools/control/build-xen/newdom.jsp +tools/control/build-xen/tmpl/about.tmpl +tools/control/build-xen/tmpl/dom-del.tmpl +tools/control/build-xen/tmpl/dom-delr.tmpl +tools/control/build-xen/tmpl/dom-lis.tmpl +tools/control/build-xen/tmpl/dom-new.tmpl +tools/control/build-xen/tmpl/dom-newr.tmpl +tools/control/build-xen/tmpl/dom-sta.tmpl +tools/control/build-xen/tmpl/dom-star.tmpl +tools/control/build-xen/tmpl/dom-stp.tmpl +tools/control/build-xen/tmpl/dom-stpr.tmpl +tools/control/build-xen/tmpl/dom.tmpl +tools/control/build-xen/tmpl/dommenu.tmpl +tools/control/build-xen/tmpl/help.tmpl +tools/control/build-xen/tmpl/index.tmpl +tools/control/build-xen/tmpl/install.pl +tools/control/build-xen/tmpl/makefile +tools/control/build-xen/tmpl/newdom.tmpl +tools/control/build-xen/tmpl/vd-fv.tmpl +tools/control/build-xen/tmpl/vd-pa.tmpl +tools/control/build-xen/tmpl/vd-par.tmpl +tools/control/build-xen/tmpl/vd-pv.tmpl +tools/control/build-xen/tmpl/vd-vbdc.tmpl +tools/control/build-xen/tmpl/vd-vbdcr.tmpl +tools/control/build-xen/tmpl/vd-vbdd.tmpl +tools/control/build-xen/tmpl/vd-vbdf.tmpl +tools/control/build-xen/tmpl/vd-vbdfr.tmpl +tools/control/build-xen/tmpl/vd-vbdv.tmpl +tools/control/build-xen/tmpl/vd-vdc.tmpl +tools/control/build-xen/tmpl/vd-vdcr.tmpl +tools/control/build-xen/tmpl/vd-vdd.tmpl +tools/control/build-xen/tmpl/vd-vddr.tmpl +tools/control/build-xen/tmpl/vd-vdr.tmpl +tools/control/build-xen/tmpl/vd-vdrr.tmpl +tools/control/build-xen/tmpl/vd-vdv.tmpl +tools/control/build-xen/tmpl/vd.tmpl +tools/control/build-xen/tmpl/vdmenu.tmpl +tools/control/build-xen/tmpl/xenofoot.def +tools/control/build-xen/tmpl/xenohead.def +tools/control/build-xen/tmpl/xenostyle.css +tools/control/build-xen/vd-fv.jsp +tools/control/build-xen/vd-pa.jsp +tools/control/build-xen/vd-par.jsp +tools/control/build-xen/vd-pv.jsp +tools/control/build-xen/vd-vbdc.jsp +tools/control/build-xen/vd-vbdcr.jsp +tools/control/build-xen/vd-vbdd.jsp +tools/control/build-xen/vd-vbdf.jsp +tools/control/build-xen/vd-vbdfr.jsp +tools/control/build-xen/vd-vbdv.jsp +tools/control/build-xen/vd-vdc.jsp +tools/control/build-xen/vd-vdcr.jsp +tools/control/build-xen/vd-vdd.jsp +tools/control/build-xen/vd-vddr.jsp +tools/control/build-xen/vd-vdr.jsp +tools/control/build-xen/vd-vdrr.jsp +tools/control/build-xen/vd-vdv.jsp +tools/control/build-xen/vd.jsp +tools/control/build-xen/xenostyle.css +tools/control/dist-web/** +tools/control/dist/docs/api/allclasses-frame.html +tools/control/dist/docs/api/allclasses-noframe.html +tools/control/dist/docs/api/constant-values.html +tools/control/dist/docs/api/deprecated-list.html +tools/control/dist/docs/api/help-doc.html +tools/control/dist/docs/api/index-all.html +tools/control/dist/docs/api/index.html +tools/control/dist/docs/api/overview-frame.html +tools/control/dist/docs/api/overview-summary.html +tools/control/dist/docs/api/overview-tree.html +tools/control/dist/docs/api/package-list +tools/control/dist/docs/api/packages.html +tools/control/dist/docs/api/stylesheet.css +tools/control/dist/docs/api/uk/ac/cam/cl/xeno/domctl/Command.html +tools/control/dist/docs/api/uk/ac/cam/cl/xeno/domctl/CommandDestroy.html +tools/control/dist/docs/api/uk/ac/cam/cl/xeno/domctl/CommandHelp.html +tools/control/dist/docs/api/uk/ac/cam/cl/xeno/domctl/CommandList.html +tools/control/dist/docs/api/uk/ac/cam/cl/xeno/domctl/CommandNew.html +tools/control/dist/docs/api/uk/ac/cam/cl/xeno/domctl/CommandStart.html +tools/control/dist/docs/api/uk/ac/cam/cl/xeno/domctl/CommandStop.html +tools/control/dist/docs/api/uk/ac/cam/cl/xeno/domctl/Defaults.html +tools/control/dist/docs/api/uk/ac/cam/cl/xeno/domctl/Domain.html +tools/control/dist/docs/api/uk/ac/cam/cl/xeno/domctl/InetAddressPattern.html +tools/control/dist/docs/api/uk/ac/cam/cl/xeno/domctl/Main.html +tools/control/dist/docs/api/uk/ac/cam/cl/xeno/domctl/Settings.html +tools/control/dist/docs/api/uk/ac/cam/cl/xeno/domctl/StringPattern.html +tools/control/dist/docs/api/uk/ac/cam/cl/xeno/domctl/package-frame.html +tools/control/dist/docs/api/uk/ac/cam/cl/xeno/domctl/package-summary.html +tools/control/dist/docs/api/uk/ac/cam/cl/xeno/domctl/package-tree.html +tools/control/dist/docs/api/uk/ac/cam/cl/xeno/xenctl/Extent.html +tools/control/dist/docs/api/uk/ac/cam/cl/xeno/xenctl/Library.html +tools/control/dist/docs/api/uk/ac/cam/cl/xeno/xenctl/Mode.html +tools/control/dist/docs/api/uk/ac/cam/cl/xeno/xenctl/Parser.html +tools/control/dist/docs/api/uk/ac/cam/cl/xeno/xenctl/Partition.html +tools/control/dist/docs/api/uk/ac/cam/cl/xeno/xenctl/PartitionManager.html +tools/control/dist/docs/api/uk/ac/cam/cl/xeno/xenctl/RootBean.html +tools/control/dist/docs/api/uk/ac/cam/cl/xeno/xenctl/SystemConfigurationBean.html +tools/control/dist/docs/api/uk/ac/cam/cl/xeno/xenctl/VirtualBlockDevice.html +tools/control/dist/docs/api/uk/ac/cam/cl/xeno/xenctl/VirtualDisk.html +tools/control/dist/docs/api/uk/ac/cam/cl/xeno/xenctl/VirtualDiskManager.html +tools/control/dist/docs/api/uk/ac/cam/cl/xeno/xenctl/XML.html +tools/control/dist/docs/api/uk/ac/cam/cl/xeno/xenctl/XMLHelper.html +tools/control/dist/docs/api/uk/ac/cam/cl/xeno/xenctl/package-frame.html +tools/control/dist/docs/api/uk/ac/cam/cl/xeno/xenctl/package-summary.html +tools/control/dist/docs/api/uk/ac/cam/cl/xeno/xenctl/package-tree.html +tools/control/dist/docs/empty_dir +tools/control/dist/xenctl-0.1-dev.war +tools/control/domctl.jar +tools/control/eclipsebin/** +tools/control/web/about.jsp +tools/control/web/dom-del.jsp +tools/control/web/dom-delr.jsp +tools/control/web/dom-lis.jsp +tools/control/web/dom-new.jsp +tools/control/web/dom-newr.jsp +tools/control/web/dom-sta.jsp +tools/control/web/dom-star.jsp +tools/control/web/dom-stp.jsp +tools/control/web/dom-stpr.jsp +tools/control/web/dom.jsp +tools/control/web/help.jsp +tools/control/web/index.jsp +tools/control/web/newdom.jsp +tools/control/web/pd-g.jsp +tools/control/web/pd-gr.jsp +tools/control/web/pd-l.jsp +tools/control/web/pd-r.jsp +tools/control/web/pd-rr.jsp +tools/control/web/pd.jsp +tools/control/web/vd-fv.jsp +tools/control/web/vd-pa.jsp +tools/control/web/vd-par.jsp +tools/control/web/vd-pv.jsp +tools/control/web/vd-vbdc.jsp +tools/control/web/vd-vbdcr.jsp +tools/control/web/vd-vbdd.jsp +tools/control/web/vd-vbdf.jsp +tools/control/web/vd-vbdfr.jsp +tools/control/web/vd-vbdv.jsp +tools/control/web/vd-vdc.jsp +tools/control/web/vd-vdcr.jsp +tools/control/web/vd-vdd.jsp +tools/control/web/vd-vddr.jsp +tools/control/web/vd-vdr.jsp +tools/control/web/vd-vdrr.jsp +tools/control/web/vd-vdv.jsp +tools/control/web/vd.jsp +tools/control/web/xenostyle.css +tools/control/xenctl-cmdline.jar +tools/domain_builder/dom_builder.o +tools/domain_builder/dom_kill.o +tools/domain_builder/domain_builder +tools/domain_builder/kill_domain +tools/domctl/build/uk/ac/cam/cl/xeno/domctl/Command.class +tools/domctl/build/uk/ac/cam/cl/xeno/domctl/CommandDestroy.class +tools/domctl/build/uk/ac/cam/cl/xeno/domctl/CommandHelp.class +tools/domctl/build/uk/ac/cam/cl/xeno/domctl/CommandNew.class +tools/domctl/build/uk/ac/cam/cl/xeno/domctl/CommandStart.class +tools/domctl/build/uk/ac/cam/cl/xeno/domctl/CommandStop.class +tools/domctl/build/uk/ac/cam/cl/xeno/domctl/Defaults$Handler.class +tools/domctl/build/uk/ac/cam/cl/xeno/domctl/Defaults.class +tools/domctl/build/uk/ac/cam/cl/xeno/domctl/InetAddressPattern.class +tools/domctl/build/uk/ac/cam/cl/xeno/domctl/Main.class +tools/domctl/build/uk/ac/cam/cl/xeno/domctl/Settings.class +tools/domctl/build/uk/ac/cam/cl/xeno/domctl/StringPattern.class +tools/domctl/domctl.jar +tools/internal/xi_build +tools/internal/xi_build.o +tools/internal/xi_create +tools/internal/xi_create.o +tools/internal/xi_destroy +tools/internal/xi_destroy.o +tools/internal/xi_list +tools/internal/xi_phys_grant +tools/internal/xi_phys_grant.c~ +tools/internal/xi_phys_grant.o +tools/internal/xi_phys_probe +tools/internal/xi_phys_probe.c~ +tools/internal/xi_phys_probe.o +tools/internal/xi_phys_revoke +tools/internal/xi_phys_revoke.c~ +tools/internal/xi_phys_revoke.o +tools/internal/xi_restore_linux +tools/internal/xi_save_linux +tools/internal/xi_sched_domain +tools/internal/xi_sched_global +tools/internal/xi_start +tools/internal/xi_start.o +tools/internal/xi_stop +tools/internal/xi_stop.o +tools/internal/xi_usage +tools/internal/xi_vbd_add +tools/internal/xi_vbd_create +tools/internal/xi_vbd_info +tools/internal/xi_vbd_list +tools/internal/xi_vif_params tools/misc/miniterm/miniterm -tools/misc/xen_read_console tools/misc/xen_cpuperf tools/misc/xen_log +tools/misc/xen_netwatch +tools/misc/xen_read_console +tools/misc/xen_refresh_dev +tools/vdmanager/build/uk/ac/cam/cl/xeno/vdmanager/Extent.class +tools/vdmanager/build/uk/ac/cam/cl/xeno/vdmanager/Library.class +tools/vdmanager/build/uk/ac/cam/cl/xeno/vdmanager/Main.class +tools/vdmanager/build/uk/ac/cam/cl/xeno/vdmanager/Mode.class +tools/vdmanager/build/uk/ac/cam/cl/xeno/vdmanager/Parser.class +tools/vdmanager/build/uk/ac/cam/cl/xeno/vdmanager/Partition.class +tools/vdmanager/build/uk/ac/cam/cl/xeno/vdmanager/PartitionManager.class +tools/vdmanager/build/uk/ac/cam/cl/xeno/vdmanager/VirtualBlockDevice.class +tools/vdmanager/build/uk/ac/cam/cl/xeno/vdmanager/VirtualDisk.class +tools/vdmanager/build/uk/ac/cam/cl/xeno/vdmanager/VirtualDiskManager.class +tools/vdmanager/build/uk/ac/cam/cl/xeno/vdmanager/XML.class +tools/vdmanager/build/uk/ac/cam/cl/xeno/vdmanager/XMLHelper.class +tools/vdmanager/vdmanager.jar +tools/xc/lib/libxc.a +tools/xc/lib/libxc.so +tools/xc/lib/libxc.so.1.3 +tools/xc/lib/libxc.so.1.3.0 +tools/xc/lib/libxc_bvtsched.o +tools/xc/lib/libxc_domain.o +tools/xc/lib/libxc_linux_build.o +tools/xc/lib/libxc_linux_restore.o +tools/xc/lib/libxc_linux_save.o +tools/xc/lib/libxc_misc.o +tools/xc/lib/libxc_private.o +tools/xc/lib/libxc_vbd.o +tools/xc/lib/libxc_vif.o +tools/xc/lib/xc_bvtsched.o +tools/xc/lib/xc_domain.o +tools/xc/lib/xc_evtchn.o +tools/xc/lib/xc_linux_build.o +tools/xc/lib/xc_linux_restore.o +tools/xc/lib/xc_linux_save.o +tools/xc/lib/xc_misc.o +tools/xc/lib/xc_netbsd_build.o +tools/xc/lib/xc_physdev.o +tools/xc/lib/xc_private.o +tools/xc/lib/xc_vbd.o +tools/xc/lib/xc_vif.o +tools/xc/py/XenoUtil.pyc +tools/xc/py/build/lib.linux-i686-2.2/Xc.so +tools/xc/py/build/lib/XenoUtil.py +tools/xc/py/build/temp.linux-i686-2.2/Xc.o +tools/xend/xend +tools/xend/xend.o +tools/xend/xend_utils.o tools/xentrace/xentrace -xen/xen -xen/xen.gz -xen/xen.s +xen-2.4.16/common/domain.c.smh +xen-2.4.16/common/kernel.c.ok-ish +xen-2.4.16/common/kernel.c.old +xen-2.4.16/drivers/block/ll_rw_blk.c.orig +xen-2.4.16/drivers/ide/ide-disk.c.orig +xen-2.4.16/drivers/ide/ide-probe.c.orig +xen-2.4.16/drivers/ide/ide-taskfile.c.orig +xen-2.4.16/drivers/ide/ide.c.orig +xen-2.4.16/drivers/net/e1000/e1000.o +xen-2.4.16/drivers/net/e1000/e1000_ethtool.o +xen-2.4.16/drivers/net/e1000/e1000_hw.o +xen-2.4.16/drivers/net/e1000/e1000_main.o +xen-2.4.16/drivers/net/e1000/e1000_param.o +xen-2.4.16/foo +xen-2.4.16/include/hypervisor-ifs/block.h.orig +xen-2.4.16/include/xeno/blkdev.h.orig +xen-2.4.16/include/xeno/sched.h.orig +xen-2.4.16/size.image +xen/BLOG +xen/arch/i386/acpitable.o +xen/arch/i386/apic.o +xen/arch/i386/arch.o +xen/arch/i386/boot/boot.o +xen/arch/i386/delay.o +xen/arch/i386/entry.o +xen/arch/i386/extable.o +xen/arch/i386/flushtlb.o +xen/arch/i386/i387.o +xen/arch/i386/i8259.o +xen/arch/i386/idle0_task.o +xen/arch/i386/io_apic.o +xen/arch/i386/ioremap.o +xen/arch/i386/irq.o +xen/arch/i386/mm.o +xen/arch/i386/mpparse.o +xen/arch/i386/nmi.o +xen/arch/i386/pci-dma.o +xen/arch/i386/pci-i386.o +xen/arch/i386/pci-irq.o +xen/arch/i386/pci-pc.o +xen/arch/i386/pdb-stub.o +xen/arch/i386/process.o +xen/arch/i386/rwlock.o +xen/arch/i386/setup.o +xen/arch/i386/smp.o +xen/arch/i386/smpboot.o +xen/arch/i386/time.o +xen/arch/i386/trampoline.o +xen/arch/i386/traps.o +xen/arch/i386/usercopy.o +xen/common/ac_timer.o +xen/common/block.o +xen/common/brlock.o +xen/common/common.o +xen/common/console.o +xen/common/debug-linux.o +xen/common/debug.c~ +xen/common/debug.o +xen/common/dom0_ops.o +xen/common/dom_mem_ops.o +xen/common/domain.o +xen/common/domain_page.o +xen/common/event.o +xen/common/event_channel.o +xen/common/kernel.o +xen/common/keyhandler.o +xen/common/lib.o +xen/common/memory.o +xen/common/network.o +xen/common/page_alloc.o +xen/common/perfc.o +xen/common/physdev.o +xen/common/rbtree.o +xen/common/resource.o +xen/common/schedule.o +xen/common/shadow.o +xen/common/slab.o +xen/common/softirq.o +xen/common/string.o +xen/common/timer.o +xen/common/trace.o +xen/common/vsprintf.o +xen/drivers/block/blkpg.o +xen/drivers/block/cciss.o +xen/drivers/block/cciss_scsi.o +xen/drivers/block/driver.o +xen/drivers/block/elevator.o +xen/drivers/block/genhd.o +xen/drivers/block/ll_rw_blk.o +xen/drivers/block/xen_block.c~ +xen/drivers/block/xen_block.o +xen/drivers/block/xen_physdisk.c~ +xen/drivers/block/xen_physdisk.o +xen/drivers/block/xen_segment.o +xen/drivers/block/xen_vbd.o +xen/drivers/cdrom/cdrom.o +xen/drivers/cdrom/driver.o +xen/drivers/char/console.o +xen/drivers/char/driver.o +xen/drivers/char/keyboard.o +xen/drivers/char/serial.o +xen/drivers/char/xen_kbd.o +xen/drivers/char/xen_serial.o +xen/drivers/ide/driver.o +xen/drivers/ide/ide-cd.o +xen/drivers/ide/ide-disk.o +xen/drivers/ide/ide-dma.o +xen/drivers/ide/ide-features.o +xen/drivers/ide/ide-geometry.o +xen/drivers/ide/ide-pci.o +xen/drivers/ide/ide-probe.o +xen/drivers/ide/ide-taskfile.o +xen/drivers/ide/ide-xeno.o +xen/drivers/ide/ide.o +xen/drivers/ide/piix.o +xen/drivers/message/fusion/driver.o +xen/drivers/message/fusion/mptbase.o +xen/drivers/message/fusion/mptscsih.o +xen/drivers/net/3c59x.o +xen/drivers/net/8139too.o +xen/drivers/net/Space.o +xen/drivers/net/driver.o +xen/drivers/net/dummy.o +xen/drivers/net/e100/e100.o +xen/drivers/net/e100/e100_config.o +xen/drivers/net/e100/e100_eeprom.o +xen/drivers/net/e100/e100_main.o +xen/drivers/net/e100/e100_phy.o +xen/drivers/net/e100/e100_test.o +xen/drivers/net/e1000/e1000.o +xen/drivers/net/e1000/e1000_ethtool.o +xen/drivers/net/e1000/e1000_hw.o +xen/drivers/net/e1000/e1000_main.o +xen/drivers/net/e1000/e1000_param.o +xen/drivers/net/e1000/kcompat.o +xen/drivers/net/ne/8390.o +xen/drivers/net/ne/ne.o +xen/drivers/net/ne/ne_drv.o +xen/drivers/net/net_init.o +xen/drivers/net/pcnet32.o +xen/drivers/net/setup.o +xen/drivers/net/tg3.o +xen/drivers/net/tulip/21142.o +xen/drivers/net/tulip/eeprom.o +xen/drivers/net/tulip/interrupt.o +xen/drivers/net/tulip/media.o +xen/drivers/net/tulip/pnic.o +xen/drivers/net/tulip/pnic2.o +xen/drivers/net/tulip/timer.o +xen/drivers/net/tulip/tulip.o +xen/drivers/net/tulip/tulip_core.o +xen/drivers/net/via-rhine.o xen/drivers/pci/classlist.h +xen/drivers/pci/compat.o xen/drivers/pci/devlist.h +xen/drivers/pci/driver.o xen/drivers/pci/gen-devlist +xen/drivers/pci/names.o +xen/drivers/pci/pci.o +xen/drivers/pci/quirks.o +xen/drivers/pci/setup-res.o +xen/drivers/scsi/BusLogic.o +xen/drivers/scsi/aacraid/aachba.o +xen/drivers/scsi/aacraid/aacraid.o +xen/drivers/scsi/aacraid/commctrl.o +xen/drivers/scsi/aacraid/comminit.o +xen/drivers/scsi/aacraid/commsup.o +xen/drivers/scsi/aacraid/dpcsup.o +xen/drivers/scsi/aacraid/linit.o +xen/drivers/scsi/aacraid/rx.o +xen/drivers/scsi/aacraid/sa.o +xen/drivers/scsi/aic7xxx/aic7770.o +xen/drivers/scsi/aic7xxx/aic7770_osm.o +xen/drivers/scsi/aic7xxx/aic79xx_core.o +xen/drivers/scsi/aic7xxx/aic79xx_osm.o +xen/drivers/scsi/aic7xxx/aic79xx_osm_pci.o +xen/drivers/scsi/aic7xxx/aic79xx_pci.o +xen/drivers/scsi/aic7xxx/aic79xx_proc.o +xen/drivers/scsi/aic7xxx/aic7xxx.o +xen/drivers/scsi/aic7xxx/aic7xxx_93cx6.o +xen/drivers/scsi/aic7xxx/aic7xxx_core.o +xen/drivers/scsi/aic7xxx/aic7xxx_osm.o +xen/drivers/scsi/aic7xxx/aic7xxx_osm_pci.o +xen/drivers/scsi/aic7xxx/aic7xxx_pci.o +xen/drivers/scsi/aic7xxx/aic7xxx_proc.o +xen/drivers/scsi/constants.o +xen/drivers/scsi/driver.o +xen/drivers/scsi/hosts.o +xen/drivers/scsi/megaraid.o +xen/drivers/scsi/scsi.o +xen/drivers/scsi/scsi_dma.o +xen/drivers/scsi/scsi_error.o +xen/drivers/scsi/scsi_ioctl.o +xen/drivers/scsi/scsi_lib.o +xen/drivers/scsi/scsi_merge.o +xen/drivers/scsi/scsi_obsolete.o +xen/drivers/scsi/scsi_proc.o +xen/drivers/scsi/scsi_queue.o +xen/drivers/scsi/scsi_scan.o +xen/drivers/scsi/scsi_syms.o +xen/drivers/scsi/scsicam.o +xen/drivers/scsi/sd.o +xen/drivers/scsi/sym53c8xx_2/sym53c8xx.o +xen/drivers/scsi/sym53c8xx_2/sym_fw.o +xen/drivers/scsi/sym53c8xx_2/sym_glue.o +xen/drivers/scsi/sym53c8xx_2/sym_hipd.o +xen/drivers/scsi/sym53c8xx_2/sym_malloc.o +xen/drivers/scsi/sym53c8xx_2/sym_misc.o +xen/drivers/scsi/sym53c8xx_2/sym_nvram.o +xen/image +xen/image.dis +xen/image.gz +xen/image.s xen/include/asm xen/include/hypervisor-ifs/arch +xen/include/hypervisor-ifs/hypervisor-ifs +xen/include/hypervisor-ifs/segment.h~ +xen/include/linux xen/include/xen/compile.h +xen/include/xeno/compile.h +xen/include/xeno/physdisk.h~ +xen/net/dev.o +xen/net/dev_mcast.o +xen/net/devinit.o +xen/net/eth.o +xen/net/network.o +xen/net/skbuff.o xen/tools/elf-reloc xen/tools/figlet/figlet -TAGS +xen/xen +xen/xen.gz +xen/xen.s +xenolinux-2.4.16-sparse/arch/xeno/drivers/block/Makefile.orig +xenolinux-2.4.16-sparse/arch/xeno/drivers/block/block.c.orig +xenolinux-2.4.16-sparse/scripts/kconfig.tk +xenolinux-2.4.21-sparse/arch/xeno/drivers/block/xl_block.c~ +xenolinux-2.4.21-sparse/arch/xeno/drivers/block/xl_physdisk_proc.c.bak +xenolinux-2.4.21-sparse/arch/xeno/drivers/block/xl_physdisk_proc.c~ +xenolinux-2.4.21-sparse/include/linux/blk.h~ +xenolinux-2.4.22-sparse/arch/xeno/drivers/block/device diff --git a/xen/arch/i386/domain_page.c b/xen/arch/i386/domain_page.c index 69c6166111..d276979a71 100644 --- a/xen/arch/i386/domain_page.c +++ b/xen/arch/i386/domain_page.c @@ -45,6 +45,8 @@ void *map_domain_mem(unsigned long pa) unsigned long *cache = mapcache; unsigned long flags; + perfc_incrc(map_domain_mem_count); + spin_lock_irqsave(&map_lock, flags); /* Has some other CPU caused a wrap? We must flush if so. */ diff --git a/xen/arch/i386/process.c b/xen/arch/i386/process.c index 939acddc13..6bcb901f32 100644 --- a/xen/arch/i386/process.c +++ b/xen/arch/i386/process.c @@ -29,9 +29,9 @@ #include <asm/i387.h> #include <asm/mpspec.h> #include <asm/ldt.h> - #include <xen/irq.h> #include <xen/event.h> +#include <xen/shadow.h> int hlt_counter; @@ -281,7 +281,13 @@ void switch_to(struct task_struct *prev_p, struct task_struct *next_p) } /* Switch page tables. */ - write_cr3_counted(pagetable_val(next_p->mm.pagetable)); + if( next_p->mm.shadow_mode ) + { + check_pagetable( next_p, next_p->mm.pagetable, "switch" ); + write_cr3_counted(pagetable_val(next_p->mm.shadow_table)); + } + else + write_cr3_counted(pagetable_val(next_p->mm.pagetable)); set_current(next_p); diff --git a/xen/arch/i386/traps.c b/xen/arch/i386/traps.c index 1c514aea23..8ee67406d2 100644 --- a/xen/arch/i386/traps.c +++ b/xen/arch/i386/traps.c @@ -39,6 +39,7 @@ #include <xen/spinlock.h> #include <xen/irq.h> #include <xen/perfc.h> +#include <xen/shadow.h> #include <asm/domain_page.h> #include <asm/system.h> #include <asm/io.h> @@ -323,6 +324,8 @@ asmlinkage void do_page_fault(struct pt_regs *regs, long error_code) __asm__ __volatile__ ("movl %%cr2,%0" : "=r" (addr) : ); + perfc_incrc(page_faults); + if ( unlikely(addr >= LDT_VIRT_START) && (addr < (LDT_VIRT_START + (p->mm.ldt_ents*LDT_ENTRY_SIZE))) ) { @@ -336,6 +339,12 @@ asmlinkage void do_page_fault(struct pt_regs *regs, long error_code) return; /* successfully copied the mapping */ } + if ( unlikely( p->mm.shadow_mode ) && addr < PAGE_OFFSET && + shadow_fault( addr, error_code ) ) + { + return; // return true if fault was handled + } + if ( unlikely(!(regs->xcs & 3)) ) goto fault_in_hypervisor; @@ -353,7 +362,8 @@ asmlinkage void do_page_fault(struct pt_regs *regs, long error_code) if ( likely((fixup = search_exception_table(regs->eip)) != 0) ) { - DPRINTK("Page fault: %08lx -> %08lx\n", regs->eip, fixup); + perfc_incrc(copy_user_faults); + //DPRINTK("copy_user fault: %08lx -> %08lx\n", regs->eip, fixup); regs->eip = fixup; regs->xds = regs->xes = regs->xfs = regs->xgs = __HYPERVISOR_DS; return; diff --git a/xen/common/debug.c b/xen/common/debug.c index 988e09d2e8..b6717ae9f4 100644 --- a/xen/common/debug.c +++ b/xen/common/debug.c @@ -91,7 +91,11 @@ int pdb_change_values(domid_t domain, u_char *buffer, unsigned long addr, if ((addr >> PAGE_SHIFT) == ((addr + length - 1) >> PAGE_SHIFT)) { - l2_table = map_domain_mem(pagetable_val(p->mm.pagetable)); + if (p->mm.shadow_mode ) + l2_table = map_domain_mem(pagetable_val(p->mm.shadow_table)); + else + l2_table = map_domain_mem(pagetable_val(p->mm.pagetable)); + l2_table += l2_table_offset(addr); if (!(l2_pgentry_val(*l2_table) & _PAGE_PRESENT)) { diff --git a/xen/common/domain.c b/xen/common/domain.c index 1fd3dbc46b..0783f7f838 100644 --- a/xen/common/domain.c +++ b/xen/common/domain.c @@ -9,6 +9,7 @@ #include <xen/delay.h> #include <xen/event.h> #include <xen/time.h> +#include <xen/shadow.h> #include <hypervisor-ifs/dom0_ops.h> #include <asm/io.h> #include <asm/domain_page.h> @@ -332,12 +333,14 @@ void free_domain_page(struct pfn_info *page) if ( !(page->count_and_flags & PGC_zombie) ) { page->tlbflush_timestamp = tlbflush_clock; - page->u.cpu_mask = 1 << p->processor; - - spin_lock(&p->page_list_lock); - list_del(&page->list); - p->tot_pages--; - spin_unlock(&p->page_list_lock); + if (p) + { + page->u.cpu_mask = 1 << p->processor; + spin_lock(&p->page_list_lock); + list_del(&page->list); + p->tot_pages--; + spin_unlock(&p->page_list_lock); + } } page->count_and_flags = 0; @@ -846,6 +849,10 @@ int setup_guestos(struct task_struct *p, dom0_createdomain_t *params, set_bit(PF_CONSTRUCTED, &p->flags); +#if 0 // XXXXX DO NOT CHECK IN ENBALED !!! (but useful for testing so leave) + shadow_mode_enable(p, SHM_test); +#endif + new_thread(p, (unsigned long)virt_load_address, (unsigned long)virt_stack_address, diff --git a/xen/common/kernel.c b/xen/common/kernel.c index 25e763f7c2..64ef966a3b 100644 --- a/xen/common/kernel.c +++ b/xen/common/kernel.c @@ -107,6 +107,7 @@ void cmain(unsigned long magic, multiboot_info_t *mbi) module_t *mod; void *heap_start; int i; + unsigned long frametable_pages, max_mem; /* Parse the command-line options. */ cmdline = (unsigned char *)(mbi->cmdline ? __va(mbi->cmdline) : NULL); @@ -196,25 +197,35 @@ void cmain(unsigned long magic, multiboot_info_t *mbi) max_page = (mbi->mem_upper+1024) >> (PAGE_SHIFT - 10); /* The array of pfn_info structures must fit into the reserved area. */ - if ( (sizeof(struct pfn_info) * max_page) > + if ( (sizeof(struct pfn_info) * max_page) > (FRAMETABLE_VIRT_END - FRAMETABLE_VIRT_START) ) { - unsigned long new_max = + unsigned long new_max = (FRAMETABLE_VIRT_END - FRAMETABLE_VIRT_START) / sizeof(struct pfn_info); - printk("Truncating available memory to %lu/%luMB\n", + printk("Truncating available memory to %lu/%luMB\n", new_max >> (20 - PAGE_SHIFT), max_page >> (20 - PAGE_SHIFT)); - max_page = new_max; + max_page = new_max; } set_current(&idle0_task); init_frametable(max_page); - printk("Initialised all memory on a %luMB machine\n", - max_page >> (20-PAGE_SHIFT)); + printk("Initialised %luMB memory on a %luMB machine\n", + max_page >> (20-PAGE_SHIFT), + max_mem >> (20-PAGE_SHIFT) ); heap_start = memguard_init(&_end); + printk("Xen heap size is %luKB\n", + (MAX_MONITOR_ADDRESS-__pa(heap_start))/1024 ); + + if ( ((MAX_MONITOR_ADDRESS-__pa(heap_start))/1024) <= 4096 ) + { + printk("Xen heap size is too small to safely continue!\n"); + for ( ; ; ) ; + } + init_page_allocator(__pa(heap_start), MAX_MONITOR_ADDRESS); /* Initialise the slab allocator. */ diff --git a/xen/common/memory.c b/xen/common/memory.c index efd75883c1..c8510c514d 100644 --- a/xen/common/memory.c +++ b/xen/common/memory.c @@ -133,6 +133,7 @@ #include <xen/errno.h> #include <xen/perfc.h> #include <xen/interrupt.h> +#include <xen/shadow.h> #include <asm/page.h> #include <asm/flushtlb.h> #include <asm/io.h> @@ -182,6 +183,7 @@ static struct { struct task_struct *subject_p; } percpu_info[NR_CPUS] __cacheline_aligned; + /* * init_frametable: * Initialise per-frame memory information. This goes directly after @@ -762,9 +764,25 @@ void free_page_type(struct pfn_info *page, unsigned int type) switch ( type ) { case PGT_l1_page_table: - return free_l1_table(page); + free_l1_table(page); + if ( unlikely(current->mm.shadow_mode) && + (get_shadow_status(current, page-frame_table) & PSH_shadowed) ) + { + unshadow_table( page-frame_table, type ); + put_shadow_status(current); + } + return; + case PGT_l2_page_table: - return free_l2_table(page); + free_l2_table(page); + if ( unlikely(current->mm.shadow_mode) && + (get_shadow_status(current, page-frame_table) & PSH_shadowed) ) + { + unshadow_table( page-frame_table, type ); + put_shadow_status(current); + } + return; + default: BUG(); } @@ -831,11 +849,22 @@ static int do_extended_command(unsigned long ptr, unsigned long val) if ( likely(okay) ) { invalidate_shadow_ldt(); + percpu_info[cpu].deferred_ops &= ~DOP_FLUSH_TLB; old_base_pfn = pagetable_val(current->mm.pagetable) >> PAGE_SHIFT; current->mm.pagetable = mk_pagetable(pfn << PAGE_SHIFT); - write_cr3_counted(pfn << PAGE_SHIFT); - put_page_and_type(&frame_table[old_base_pfn]); + + if( unlikely(current->mm.shadow_mode)) + { + current->mm.shadow_table = + shadow_mk_pagetable(current, pfn<<PAGE_SHIFT); + write_cr3_counted(pagetable_val(current->mm.shadow_table)); + } + else + { + write_cr3_counted(pfn << PAGE_SHIFT); + } + put_page_and_type(&frame_table[old_base_pfn]); } else { @@ -919,6 +948,8 @@ int do_mmu_update(mmu_update_t *ureqs, int count) struct pfn_info *page; int rc = 0, okay = 1, i, cpu = smp_processor_id(); unsigned int cmd; + unsigned long prev_spfn = 0; + l1_pgentry_t *prev_spl1e = 0; perfc_incrc(calls_to_mmu_update); perfc_addc(num_page_updates, count); @@ -969,6 +1000,16 @@ int do_mmu_update(mmu_update_t *ureqs, int count) { okay = mod_l1_entry((l1_pgentry_t *)va, mk_l1_pgentry(req.val)); + + if ( okay && unlikely(current->mm.shadow_mode) && + (get_shadow_status(current, page-frame_table) & + PSH_shadowed) ) + { + shadow_l1_normal_pt_update( req.ptr, req.val, + &prev_spfn, &prev_spl1e ); + put_shadow_status(current); + } + put_page_type(page); } break; @@ -978,6 +1019,15 @@ int do_mmu_update(mmu_update_t *ureqs, int count) okay = mod_l2_entry((l2_pgentry_t *)va, mk_l2_pgentry(req.val), pfn); + + if ( okay && unlikely(current->mm.shadow_mode) && + (get_shadow_status(current, page-frame_table) & + PSH_shadowed) ) + { + shadow_l2_normal_pt_update( req.ptr, req.val ); + put_shadow_status(current); + } + put_page_type(page); } break; @@ -987,10 +1037,12 @@ int do_mmu_update(mmu_update_t *ureqs, int count) *(unsigned long *)va = req.val; okay = 1; put_page_type(page); + + // at present, we don't shadowing such pages } break; } - + put_page(page); break; @@ -1033,11 +1085,23 @@ int do_mmu_update(mmu_update_t *ureqs, int count) if ( prev_pfn != 0 ) unmap_domain_mem((void *)va); + if( prev_spl1e != 0 ) + unmap_domain_mem((void *)prev_spl1e); + deferred_ops = percpu_info[cpu].deferred_ops; percpu_info[cpu].deferred_ops = 0; if ( deferred_ops & DOP_FLUSH_TLB ) - write_cr3_counted(pagetable_val(current->mm.pagetable)); + { + if ( unlikely(current->mm.shadow_mode) ) + { + check_pagetable( current, + current->mm.pagetable, "pre-stlb-flush" ); + write_cr3_counted(pagetable_val(current->mm.shadow_table)); + } + else + write_cr3_counted(pagetable_val(current->mm.pagetable)); + } if ( deferred_ops & DOP_RELOAD_LDT ) (void)map_ldt_shadow_page(0); @@ -1061,19 +1125,58 @@ int do_update_va_mapping(unsigned long page_nr, unsigned int cpu = p->processor; unsigned long deferred_ops; + perfc_incrc(calls_to_update_va); + if ( unlikely(page_nr >= (HYPERVISOR_VIRT_START >> PAGE_SHIFT)) ) return -EINVAL; + // XXX when we make this support 4MB pages we should also + // deal with the case of updating L2s + if ( unlikely(!mod_l1_entry(&linear_pg_table[page_nr], mk_l1_pgentry(val))) ) err = -EINVAL; + if ( unlikely(p->mm.shadow_mode) ) + { + unsigned long sval = 0; + + // XXX this only works for l1 entries, with no translation + + if ( (val & _PAGE_PRESENT) && (val & _PAGE_ACCESSED) ) + { + sval = val; + if ( !(val & _PAGE_DIRTY) ) + sval &= ~_PAGE_RW; + } + + /* printk("update_va_map: page_nr=%08lx val =%08lx sval =%08lx\n", + page_nr, val, sval);*/ + + if ( __put_user( sval, ((unsigned long *) (&shadow_linear_pg_table[page_nr])) ) ) + { + // Since L2's are guranteed RW, failure indicates the page + // was not shadowed, so ignore. + perfc_incrc(shadow_update_va_fail); + //MEM_LOG("update_va_map: couldn't write update\n"); + } + + check_pagetable( p, p->mm.pagetable, "va" ); // debug + + } + + deferred_ops = percpu_info[cpu].deferred_ops; percpu_info[cpu].deferred_ops = 0; if ( unlikely(deferred_ops & DOP_FLUSH_TLB) || unlikely(flags & UVMF_FLUSH_TLB) ) - write_cr3_counted(pagetable_val(p->mm.pagetable)); + { + if ( unlikely(p->mm.shadow_mode) ) + write_cr3_counted(pagetable_val(p->mm.shadow_table)); + else + write_cr3_counted(pagetable_val(p->mm.pagetable)); + } else if ( unlikely(flags & UVMF_INVLPG) ) __flush_tlb_one(page_nr << PAGE_SHIFT); diff --git a/xen/common/perfc.c b/xen/common/perfc.c index 20b0e5c116..631e81787c 100644 --- a/xen/common/perfc.c +++ b/xen/common/perfc.c @@ -8,12 +8,20 @@ #undef PERFCOUNTER #undef PERFCOUNTER_CPU #undef PERFCOUNTER_ARRAY +#undef PERFSTATUS +#undef PERFSTATUS_CPU +#undef PERFSTATUS_ARRAY #define PERFCOUNTER( var, name ) { name, TYPE_SINGLE, 0 }, #define PERFCOUNTER_CPU( var, name ) { name, TYPE_CPU, 0 }, #define PERFCOUNTER_ARRAY( var, name, size ) { name, TYPE_ARRAY, size }, +#define PERFSTATUS( var, name ) { name, TYPE_S_SINGLE, 0 }, +#define PERFSTATUS_CPU( var, name ) { name, TYPE_S_CPU, 0 }, +#define PERFSTATUS_ARRAY( var, name, size ) { name, TYPE_S_ARRAY, size }, static struct { char *name; - enum { TYPE_SINGLE, TYPE_CPU, TYPE_ARRAY } type; + enum { TYPE_SINGLE, TYPE_CPU, TYPE_ARRAY, + TYPE_S_SINGLE, TYPE_S_CPU, TYPE_S_ARRAY + } type; int nr_elements; } perfc_info[] = { #include <xen/perfc_defn.h> @@ -38,10 +46,12 @@ void perfc_printall(u_char key, void *dev_id, struct pt_regs *regs) switch ( perfc_info[i].type ) { case TYPE_SINGLE: + case TYPE_S_SINGLE: printk("TOTAL[%10d]", atomic_read(&counters[0])); counters += 1; break; case TYPE_CPU: + case TYPE_S_CPU: for ( j = sum = 0; j < smp_num_cpus; j++ ) sum += atomic_read(&counters[j]); printk("TOTAL[%10d] ", sum); @@ -50,6 +60,7 @@ void perfc_printall(u_char key, void *dev_id, struct pt_regs *regs) counters += NR_CPUS; break; case TYPE_ARRAY: + case TYPE_S_ARRAY: for ( j = sum = 0; j < perfc_info[i].nr_elements; j++ ) sum += atomic_read(&counters[j]); printk("TOTAL[%10d] ", sum); @@ -64,9 +75,37 @@ void perfc_printall(u_char key, void *dev_id, struct pt_regs *regs) void perfc_reset(u_char key, void *dev_id, struct pt_regs *regs) { + int i, j, sum; s_time_t now = NOW(); + atomic_t *counters = (atomic_t *)&perfcounters; + printk("Xen performance counters RESET (now = 0x%08X:%08X)\n", (u32)(now>>32), (u32)now); - memset(&perfcounters, 0, sizeof(perfcounters)); + + // leave STATUS counters alone -- don't reset + + for ( i = 0; i < NR_PERFCTRS; i++ ) + { + switch ( perfc_info[i].type ) + { + case TYPE_SINGLE: + atomic_set(&counters[0],0); + case TYPE_S_SINGLE: + counters += 1; + break; + case TYPE_CPU: + for ( j = sum = 0; j < smp_num_cpus; j++ ) + atomic_set(&counters[j],0); + case TYPE_S_CPU: + counters += NR_CPUS; + break; + case TYPE_ARRAY: + for ( j = sum = 0; j < perfc_info[i].nr_elements; j++ ) + atomic_set(&counters[j],0); + case TYPE_S_ARRAY: + counters += perfc_info[i].nr_elements; + break; + } + } } diff --git a/xen/common/shadow.c b/xen/common/shadow.c new file mode 100644 index 0000000000..03c5cb9a6a --- /dev/null +++ b/xen/common/shadow.c @@ -0,0 +1,793 @@ +/* -*- Mode:C; c-basic-offset:4; tab-width:4 -*- */ + +#include <xeno/config.h> +#include <xeno/types.h> +#include <xeno/mm.h> +#include <xeno/shadow.h> +#include <asm/domain_page.h> +#include <asm/page.h> + + +/******** + +To use these shadow page tables, guests must not rely on the ACCESSED +and DIRTY bits on L2 pte's being accurate -- they will typically all be set. + +I doubt this will break anything. (If guests want to use the va_update +mechanism they've signed up for this anyhow...) + +There's a per-domain shadow table spin lock which works fine for SMP +hosts. We don't have to worry about interrupts as no shadow operations +happen in an interrupt context. It's probably not quite ready for SMP +guest operation as we have to worry about synchonisation between gpte +and spte updates. Its possible that this might only happen in a +hypercall context, in which case we'll probably at have a per-domain +hypercall lock anyhow (at least initially). + +********/ + + +int shadow_mode_enable( struct task_struct *p, unsigned int mode ) +{ + struct shadow_status **fptr; + int i; + + // sychronously stop domain + // XXX for the moment, only use on already stopped domains!!! + + spin_lock_init(&p->mm.shadow_lock); + spin_lock(&p->mm.shadow_lock); + + p->mm.shadow_mode = mode; + + // allocate hashtable + p->mm.shadow_ht = kmalloc( shadow_ht_buckets * + sizeof(struct shadow_status), GFP_KERNEL ); + if( ! p->mm.shadow_ht ) + goto nomem; + + memset( p->mm.shadow_ht, 0, shadow_ht_buckets * + sizeof(struct shadow_status) ); + + + // allocate space for first lot of extra nodes + p->mm.shadow_ht_extras = kmalloc( sizeof(void*) + (shadow_ht_extra_size * + sizeof(struct shadow_status)), GFP_KERNEL ); + + if( ! p->mm.shadow_ht_extras ) + goto nomem; + + memset( p->mm.shadow_ht_extras, 0, sizeof(void*) + (shadow_ht_extra_size * + sizeof(struct shadow_status)) ); + + // add extras to free list + fptr = &p->mm.shadow_ht_free; + for ( i=0; i<shadow_ht_extra_size; i++ ) + { + *fptr = &p->mm.shadow_ht_extras[i]; + fptr = &(p->mm.shadow_ht_extras[i].next); + } + *fptr = NULL; + *((struct shadow_status ** ) &p->mm.shadow_ht_extras[shadow_ht_extra_size]) = NULL; + + spin_unlock(&p->mm.shadow_lock); + + // call shadow_mk_pagetable + p->mm.shadow_table = shadow_mk_pagetable( p, + pagetable_val(p->mm.pagetable) ); + + return 0; + +nomem: + spin_unlock(&p->mm.shadow_lock); + return -ENOMEM; +} + +void shadow_mode_disable( ) +{ + + // free the hash buckets as you go + + // free the hashtable itself +} + + +static inline void free_shadow_page( struct task_struct *p, unsigned int pfn ) +{ + unsigned long flags; + + p->mm.shadow_page_count--; + + spin_lock_irqsave(&free_list_lock, flags); + list_add(&frame_table[pfn].list, &free_list); + free_pfns++; + spin_unlock_irqrestore(&free_list_lock, flags); +} + +static inline struct pfn_info *alloc_shadow_page( struct task_struct *p ) +{ + p->mm.shadow_page_count++; + + return alloc_domain_page( NULL ); +} + + +static void __free_shadow_table( struct task_struct *p ) +{ + int j; + struct shadow_status *a; + + // the code assumes you're not using the page tables i.e. + // the domain is stopped and cr3 is something else!! + + // walk the hash table and call free_shadow_page on all pages + + for(j=0;j<shadow_ht_buckets;j++) + { + a = &p->mm.shadow_ht[j]; + if (a->pfn) + { + free_shadow_page( p, a->spfn_and_flags & PSH_pfn_mask ); + a->pfn = 0; + a->spfn_and_flags = 0; + } + a=a->next; + while(a) + { + struct shadow_status *next = a->next; + free_shadow_page( p, a->spfn_and_flags & PSH_pfn_mask ); + a->pfn = 0; + a->spfn_and_flags = 0; + a->next = p->mm.shadow_ht_free; + p->mm.shadow_ht_free = a; + a=next; + } + } +} + +static void flush_shadow_table( struct task_struct *p ) +{ + + // XXX synchronously stop domain (needed for SMP guests) + + // switch to idle task's page tables + + // walk the hash table and call free_shadow_page on all pages + spin_lock(&p->mm.shadow_lock); + __free_shadow_table( p ); + spin_unlock(&p->mm.shadow_lock); + + // XXX unpause domain +} + + + +void unshadow_table( unsigned long gpfn, unsigned int type ) +{ + unsigned long spfn; + + SH_VLOG("unshadow_table type=%08x gpfn=%08lx", + type, + gpfn ); + + perfc_incrc(unshadow_table_count); + + // this function is the same for both l1 and l2 tables + + // even in the SMP guest case, there won't be a race here as + // this CPU was the one that cmpxchg'ed the page to invalid + + spfn = __shadow_status(current, gpfn) & PSH_pfn_mask; + delete_shadow_status(current, gpfn); + +#if 0 // XXX leave as might be useful for later debugging + { + int i; + unsigned long * spl1e = map_domain_mem( spfn<<PAGE_SHIFT ); + + for ( i = 0; i < ENTRIES_PER_L1_PAGETABLE; i++ ) + { + spl1e[i] = 0xdead0000; + } + unmap_domain_mem( spl1e ); + } +#endif + + if (type == PGT_l1_page_table) + perfc_decr(shadow_l1_pages); + else + perfc_decr(shadow_l2_pages); + + free_shadow_page( current, spfn ); + +} + + +static unsigned long shadow_l2_table( + struct task_struct *p, unsigned long gpfn ) +{ + struct pfn_info *spfn_info; + unsigned long spfn; + l2_pgentry_t *spl2e, *gpl2e; + int i; + + SH_VVLOG("shadow_l2_table( %08lx )",gpfn); + spin_lock(&p->mm.shadow_lock); + + perfc_incrc(shadow_l2_table_count); + perfc_incr(shadow_l2_pages); + + // XXX in future, worry about racing in SMP guests + // -- use cmpxchg with PSH_pending flag to show progress (and spin) + + spfn_info = alloc_shadow_page(p); + + ASSERT( spfn_info ); // XXX deal with failure later e.g. blow cache + + spfn = (unsigned long) (spfn_info - frame_table); + + // mark pfn as being shadowed, update field to point at shadow + set_shadow_status(p, gpfn, spfn | PSH_shadowed); + + // we need to do this before the linear map is set up + spl2e = (l2_pgentry_t *) map_domain_mem(spfn << PAGE_SHIFT); + + // get hypervisor and 2x linear PT mapings installed + memcpy(&spl2e[DOMAIN_ENTRIES_PER_L2_PAGETABLE], + &idle_pg_table[DOMAIN_ENTRIES_PER_L2_PAGETABLE], + HYPERVISOR_ENTRIES_PER_L2_PAGETABLE * sizeof(l2_pgentry_t)); + spl2e[LINEAR_PT_VIRT_START >> L2_PAGETABLE_SHIFT] = + mk_l2_pgentry((gpfn << PAGE_SHIFT) | __PAGE_HYPERVISOR); + spl2e[SH_LINEAR_PT_VIRT_START >> L2_PAGETABLE_SHIFT] = + mk_l2_pgentry((spfn << PAGE_SHIFT) | __PAGE_HYPERVISOR); + spl2e[PERDOMAIN_VIRT_START >> L2_PAGETABLE_SHIFT] = + mk_l2_pgentry(__pa(frame_table[gpfn].u.domain->mm.perdomain_pt) | + __PAGE_HYPERVISOR); + + // can't use the linear map as we may not be in the right PT + gpl2e = (l2_pgentry_t *) map_domain_mem(gpfn << PAGE_SHIFT); + + // proactively create entries for pages that are already shadowed + for ( i = 0; i < DOMAIN_ENTRIES_PER_L2_PAGETABLE; i++ ) + { + unsigned long spte = 0; + +#if 0 // Turns out this doesn't really help + unsigned long gpte; + + gpte = l2_pgentry_val(gpl2e[i]); + + if (gpte & _PAGE_PRESENT) + { + unsigned long s_sh = + __shadow_status(p, gpte>>PAGE_SHIFT); + + if( s_sh & PSH_shadowed ) // PSH_shadowed + { + if ( unlikely( (__shadow_status(p, gpte>>PAGE_SHIFT) & PGT_type_mask) == PGT_l2_page_table) ) + { + printk("Linear mapping detected\n"); + spte = gpte & ~_PAGE_RW; + } + else + { + spte = ( gpte & ~PAGE_MASK ) | (s_sh<<PAGE_SHIFT) | + _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED ; + } + // XXX should probably update guest to ACCESSED|DIRTY too... + + } + + } +#endif + + spl2e[i] = mk_l2_pgentry( spte ); + + } + + // its arguable we should 'preemptively shadow' a few active L1 pages + // to avoid taking a string of faults when 'jacking' a running domain + + unmap_domain_mem( gpl2e ); + unmap_domain_mem( spl2e ); + + SH_VLOG("shadow_l2_table( %08lx -> %08lx)",gpfn,spfn); + + spin_unlock(&p->mm.shadow_lock); + return spfn; +} + +pagetable_t shadow_mk_pagetable( struct task_struct *p, + unsigned long gptbase) +{ + unsigned long gpfn, spfn=0; + + SH_VVLOG("shadow_mk_pagetable( gptbase=%08lx, mode=%d )", + gptbase, p->mm.shadow_mode ); + + if ( likely(p->mm.shadow_mode) ) // should always be true if we're here + { + gpfn = gptbase >> PAGE_SHIFT; + + if ( unlikely((spfn=__shadow_status(p, gpfn)) == 0 ) ) + { + spfn = shadow_l2_table(p, gpfn ); + } + } + + SH_VVLOG("leaving shadow_mk_pagetable( gptbase=%08lx, mode=%d )", + gptbase, p->mm.shadow_mode ); + + return mk_pagetable(spfn<<PAGE_SHIFT); +} + +int shadow_fault( unsigned long va, long error_code ) +{ + unsigned long gpte, spte; + + SH_VVLOG("shadow_fault( va=%08lx, code=%ld )", va, error_code ); + + check_pagetable( current, current->mm.pagetable, "pre-sf" ); + + if ( unlikely(__get_user(gpte, (unsigned long*)&linear_pg_table[va>>PAGE_SHIFT])) ) + { + SH_VVLOG("shadow_fault - EXIT: read gpte faulted" ); + return 0; // propagate to guest + } + + if ( ! (gpte & _PAGE_PRESENT) ) + { + SH_VVLOG("shadow_fault - EXIT: gpte not present (%lx)",gpte ); + return 0; // we're not going to be able to help + } + + if ( (error_code & 2) && ! (gpte & _PAGE_RW) ) + { + // write fault on RO page + return 0; + } + + spin_lock(¤t->mm.shadow_lock); + // take the lock and reread gpte + + if ( unlikely(__get_user(gpte, (unsigned long*)&linear_pg_table[va>>PAGE_SHIFT])) ) + { + SH_VVLOG("shadow_fault - EXIT: read gpte faulted" ); + spin_unlock(¤t->mm.shadow_lock); + return 0; // propagate to guest + } + + if ( unlikely(!(gpte & _PAGE_PRESENT)) ) + { + SH_VVLOG("shadow_fault - EXIT: gpte not present (%lx)",gpte ); + spin_unlock(¤t->mm.shadow_lock); + return 0; // we're not going to be able to help + } + + spte = gpte; + + if ( error_code & 2 ) + { // write fault + if ( likely(gpte & _PAGE_RW) ) + { + gpte |= _PAGE_DIRTY | _PAGE_ACCESSED; + spte |= _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED; + // (we're about to dirty it anyhow...) + } + else + { // write fault on RO page + SH_VVLOG("shadow_fault - EXIT: write fault on RO page (%lx)",gpte ); + spin_unlock(¤t->mm.shadow_lock); + return 0; // propagate to guest + // not clear whether we should set accessed bit here... + } + } + else + { + gpte |= _PAGE_ACCESSED; + spte |= _PAGE_ACCESSED; // about to happen anyway + if ( ! (gpte & _PAGE_DIRTY) ) + spte &= ~_PAGE_RW; // force clear unless already dirty + } + + SH_VVLOG("plan: gpte=%08lx spte=%08lx", gpte, spte ); + + // write back updated gpte + // XXX watch out for read-only L2 entries! (not used in Linux) + if ( unlikely( __put_user( gpte, (unsigned long*)&linear_pg_table[va>>PAGE_SHIFT])) ) + BUG(); // fixme! + + if ( unlikely( __put_user( spte, (unsigned long*)&shadow_linear_pg_table[va>>PAGE_SHIFT])) ) + { + // failed: + // the L1 may not be shadowed, or the L2 entry may be insufficient + + unsigned long gpde, spde, gl1pfn, sl1pfn; + + SH_VVLOG("3: not shadowed or l2 insufficient gpte=%08lx spte=%08lx",gpte,spte ); + + gpde = l2_pgentry_val(linear_l2_table[va>>L2_PAGETABLE_SHIFT]); + + gl1pfn = gpde>>PAGE_SHIFT; + + + if ( ! (sl1pfn=__shadow_status(current, gl1pfn) ) ) + { + // this L1 is NOT already shadowed so we need to shadow it + struct pfn_info *sl1pfn_info; + unsigned long *gpl1e, *spl1e; + int i; + sl1pfn_info = alloc_domain_page( NULL ); // XXX account properly! + sl1pfn = sl1pfn_info - frame_table; + + SH_VVLOG("4a: l1 not shadowed ( %08lx )",sl1pfn); + perfc_incrc(shadow_l1_table_count); + perfc_incr(shadow_l1_pages); + + set_shadow_status(current, gl1pfn, PSH_shadowed | sl1pfn); + + gpde = gpde | _PAGE_ACCESSED | _PAGE_DIRTY; + spde = (gpde & ~PAGE_MASK) | _PAGE_RW | (sl1pfn<<PAGE_SHIFT); + + + linear_l2_table[va>>L2_PAGETABLE_SHIFT] = mk_l2_pgentry(gpde); + shadow_linear_l2_table[va>>L2_PAGETABLE_SHIFT] = mk_l2_pgentry(spde); + + gpl1e = (unsigned long *) &(linear_pg_table[ + (va>>PAGE_SHIFT) & ~(ENTRIES_PER_L1_PAGETABLE-1) ]); + + spl1e = (unsigned long *) &shadow_linear_pg_table[ + (va>>PAGE_SHIFT) & ~(ENTRIES_PER_L1_PAGETABLE-1) ]; + + + // XXX can only do this is the shadow/guest is writeable + // disable write protection if ! gpde & _PAGE_RW ???? + + for ( i = 0; i < ENTRIES_PER_L1_PAGETABLE; i++ ) + { +#if SHADOW_OPTIMISE + if ( (gpl1e[i] & (_PAGE_PRESENT|_PAGE_ACCESSED) ) == + (_PAGE_PRESENT|_PAGE_ACCESSED) ) + { + spl1e[i] = gpl1e[i]; + if ( !(gpl1e[i] & _PAGE_DIRTY) ) + spl1e[i] &= ~_PAGE_RW; + } + else +#endif + spl1e[i] = 0; + } + + + } + else + { + // this L1 was shadowed (by another PT) but we didn't have an L2 + // entry for it + + SH_VVLOG("4b: was shadowed, l2 missing ( %08lx )",sl1pfn); + + spde = (gpde & ~PAGE_MASK) | (sl1pfn<<PAGE_SHIFT) | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY; + + gpde = gpde | _PAGE_ACCESSED | _PAGE_DIRTY; + + + if ( unlikely( (sl1pfn<<PAGE_SHIFT) == (gl1pfn<<PAGE_SHIFT) ) ) + { // detect linear map, and keep pointing at guest + SH_VLOG("4c: linear mapping ( %08lx )",sl1pfn); + spde = (spde & ~PAGE_MASK) | (gl1pfn<<PAGE_SHIFT); + } + + linear_l2_table[va>>L2_PAGETABLE_SHIFT] = mk_l2_pgentry(gpde); + shadow_linear_l2_table[va>>L2_PAGETABLE_SHIFT] = mk_l2_pgentry(spde); + + + } + + shadow_linear_pg_table[va>>PAGE_SHIFT] = mk_l1_pgentry(spte); + // (we need to do the above even if we've just made the shadow L1) + + } // end of fixup writing the shadow L1 directly failed + + perfc_incrc(shadow_fixup_count); + + check_pagetable( current, current->mm.pagetable, "post-sf" ); + + spin_unlock(¤t->mm.shadow_lock); + + return 1; // let's try the faulting instruction again... + +} + + +void shadow_l1_normal_pt_update( unsigned long pa, unsigned long gpte, + unsigned long *prev_spfn_ptr, + l1_pgentry_t **prev_spl1e_ptr ) +{ + unsigned long gpfn, spfn, spte, prev_spfn = *prev_spfn_ptr; + l1_pgentry_t * spl1e, * prev_spl1e = *prev_spl1e_ptr; + + +SH_VVLOG("shadow_l1_normal_pt_update pa=%08lx, gpte=%08lx, prev_spfn=%08lx, prev_spl1e=%08lx\n", +pa,gpte,prev_spfn, prev_spl1e); + + // to get here, we know the l1 page *must* be shadowed + + gpfn = pa >> PAGE_SHIFT; + spfn = __shadow_status(current, gpfn) & PSH_pfn_mask; + + if ( spfn == prev_spfn ) + { + spl1e = prev_spl1e; + } + else + { + if( prev_spl1e ) unmap_domain_mem( prev_spl1e ); + spl1e = (l1_pgentry_t *) map_domain_mem( spfn << PAGE_SHIFT ); + *prev_spfn_ptr = spfn; + *prev_spl1e_ptr = spl1e; + } + // XXX we assume only pagetables can be shadowed; this will have to change + // to allow arbitrary CoW etc. + + spte = 0; + +#if SHADOW_OPTIMISE + if ( (gpte & (_PAGE_PRESENT|_PAGE_ACCESSED) ) == + (_PAGE_PRESENT|_PAGE_ACCESSED) ) + { + spte = gpte; + if ( !(gpte & _PAGE_DIRTY ) ) + gpte &= ~ _PAGE_RW; + } +#endif + + spl1e[(pa & ~PAGE_MASK) / sizeof(l1_pgentry_t) ] = + mk_l1_pgentry( spte ); + + //unmap_domain_mem( (void *) spl1e ); +} + +void shadow_l2_normal_pt_update( unsigned long pa, unsigned long gpte ) +{ + unsigned long gpfn, spfn, spte; + l2_pgentry_t * sp2le; + unsigned long s_sh=0; + + SH_VVLOG("shadow_l2_normal_pt_update pa=%08lx, gpte=%08lx",pa,gpte); + + // to get here, we know the l2 page has a shadow + + gpfn = pa >> PAGE_SHIFT; + spfn = __shadow_status(current, gpfn) & PSH_pfn_mask; + + + spte = 0; + + if( gpte & _PAGE_PRESENT ) + s_sh = __shadow_status(current, gpte >> PAGE_SHIFT); + + sp2le = (l2_pgentry_t *) map_domain_mem( spfn << PAGE_SHIFT ); + // no real need for a cache here + + if ( s_sh ) // PSH_shadowed + { + if ( unlikely( (frame_table[gpte>>PAGE_SHIFT].type_and_flags & PGT_type_mask) == PGT_l2_page_table) ) + { + // linear page table case + spte = (gpte & ~_PAGE_RW) | _PAGE_DIRTY | _PAGE_ACCESSED; + } + else + spte = (gpte & ~PAGE_MASK) | (s_sh<<PAGE_SHIFT) | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED; + + } + + // XXXX Should mark guest pte as DIRTY and ACCESSED too!!!!! + + sp2le[(pa & ~PAGE_MASK) / sizeof(l2_pgentry_t) ] = + mk_l2_pgentry( spte ); + + unmap_domain_mem( (void *) sp2le ); +} + + +#if SHADOW_DEBUG + +static int sh_l2_present; +static int sh_l1_present; +char * sh_check_name; + +#define FAIL(_f, _a...) \ +{printk("XXX %s-FAIL (%d,%d)" _f " g=%08lx s=%08lx\n", sh_check_name, level, i, ## _a , gpte, spte ); BUG();} + +static int check_pte( struct task_struct *p, + unsigned long gpte, unsigned long spte, int level, int i ) +{ + unsigned long mask, gpfn, spfn; + + if ( spte == 0 || spte == 0xdeadface || spte == 0x00000E00) + return 1; // always safe + + if ( !(spte & _PAGE_PRESENT) ) + FAIL("Non zero not present spte"); + + if( level == 2 ) sh_l2_present++; + if( level == 1 ) sh_l1_present++; + + if ( !(gpte & _PAGE_PRESENT) ) + FAIL("Guest not present yet shadow is"); + + mask = ~(_PAGE_DIRTY|_PAGE_ACCESSED|_PAGE_RW|0xFFFFF000); + + if ( (spte & mask) != (gpte & mask ) ) + FAIL("Corrupt?"); + + if ( (spte & _PAGE_DIRTY ) && !(gpte & _PAGE_DIRTY) ) + FAIL("Dirty coherence"); + + if ( (spte & _PAGE_ACCESSED ) && !(gpte & _PAGE_ACCESSED) ) + FAIL("Accessed coherence"); + + if ( (spte & _PAGE_RW ) && !(gpte & _PAGE_RW) ) + FAIL("RW coherence"); + + if ( (spte & _PAGE_RW ) && !((gpte & _PAGE_RW) && (gpte & _PAGE_DIRTY) )) + FAIL("RW2 coherence"); + + spfn = spte>>PAGE_SHIFT; + gpfn = gpte>>PAGE_SHIFT; + + if ( gpfn == spfn ) + { + if ( level > 1 ) + FAIL("Linear map ???"); // XXX this will fail on BSD + + return 1; + } + else + { + if ( level < 2 ) + FAIL("Shadow in L1 entry?"); + + if ( __shadow_status(p, gpfn) != (PSH_shadowed | spfn) ) + FAIL("spfn problem g.sf=%08lx", + __shadow_status(p, gpfn) ); + } + + return 1; +} + + +static int check_l1_table( struct task_struct *p, unsigned long va, + unsigned long g2, unsigned long s2 ) +{ + int j; + unsigned long *gpl1e, *spl1e; + + //gpl1e = (unsigned long *) &(linear_pg_table[ va>>PAGE_SHIFT]); + //spl1e = (unsigned long *) &(shadow_linear_pg_table[ va>>PAGE_SHIFT]); + + gpl1e = map_domain_mem( g2<<PAGE_SHIFT ); + spl1e = map_domain_mem( s2<<PAGE_SHIFT ); + + for ( j = 0; j < ENTRIES_PER_L1_PAGETABLE; j++ ) + { + unsigned long gpte = gpl1e[j]; + unsigned long spte = spl1e[j]; + + check_pte( p, gpte, spte, 1, j ); + } + + unmap_domain_mem( spl1e ); + unmap_domain_mem( gpl1e ); + + return 1; +} + +#define FAILPT(_f, _a...) \ +{printk("XXX FAIL %s-PT" _f "\n", s, ## _a ); BUG();} + +int check_pagetable( struct task_struct *p, pagetable_t pt, char *s ) +{ + unsigned long gptbase = pagetable_val(pt); + unsigned long gpfn, spfn; + int i; + l2_pgentry_t *gpl2e, *spl2e; + + sh_check_name = s; + + SH_VVLOG("%s-PT Audit",s); + + sh_l2_present = sh_l1_present = 0; + + gpfn = gptbase >> PAGE_SHIFT; + + if ( ! (__shadow_status(p, gpfn) & PSH_shadowed) ) + { + printk("%s-PT %08lx not shadowed\n", s, gptbase); + + if( __shadow_status(p, gpfn) != 0 ) BUG(); + + return 0; + } + + spfn = __shadow_status(p, gpfn) & PSH_pfn_mask; + + if ( ! __shadow_status(p, gpfn) == (PSH_shadowed | spfn) ) + FAILPT("ptbase shadow inconsistent1"); + + gpl2e = (l2_pgentry_t *) map_domain_mem( gpfn << PAGE_SHIFT ); + spl2e = (l2_pgentry_t *) map_domain_mem( spfn << PAGE_SHIFT ); + + //ipl2e = (l2_pgentry_t *) map_domain_mem( spfn << PAGE_SHIFT ); + + + if ( memcmp( &spl2e[DOMAIN_ENTRIES_PER_L2_PAGETABLE], + &gpl2e[DOMAIN_ENTRIES_PER_L2_PAGETABLE], + ((SH_LINEAR_PT_VIRT_START>>(L2_PAGETABLE_SHIFT))-DOMAIN_ENTRIES_PER_L2_PAGETABLE) + * sizeof(l2_pgentry_t)) ) + { + printk("gpfn=%08lx spfn=%08lx\n", gpfn, spfn); + for (i=DOMAIN_ENTRIES_PER_L2_PAGETABLE; + i<(SH_LINEAR_PT_VIRT_START>>(L2_PAGETABLE_SHIFT)); + i++ ) + printk("+++ (%d) %08lx %08lx\n",i, + l2_pgentry_val(gpl2e[i]), l2_pgentry_val(spl2e[i]) ); + FAILPT("hypervisor entries inconsistent"); + } + + if ( (l2_pgentry_val(spl2e[LINEAR_PT_VIRT_START >> L2_PAGETABLE_SHIFT]) != + l2_pgentry_val(gpl2e[LINEAR_PT_VIRT_START >> L2_PAGETABLE_SHIFT])) ) + FAILPT("hypervisor linear map inconsistent"); + + if ( (l2_pgentry_val(spl2e[SH_LINEAR_PT_VIRT_START >> L2_PAGETABLE_SHIFT]) != + ((spfn << PAGE_SHIFT) | __PAGE_HYPERVISOR)) ) + FAILPT("hypervisor shadow linear map inconsistent %08lx %08lx", + l2_pgentry_val(spl2e[SH_LINEAR_PT_VIRT_START >> L2_PAGETABLE_SHIFT]), + (spfn << PAGE_SHIFT) | __PAGE_HYPERVISOR + ); + + if ( (l2_pgentry_val(spl2e[PERDOMAIN_VIRT_START >> L2_PAGETABLE_SHIFT]) != + ((__pa(frame_table[gpfn].u.domain->mm.perdomain_pt) | __PAGE_HYPERVISOR))) ) + FAILPT("hypervisor per-domain map inconsistent"); + + + // check the whole L2 + for ( i = 0; i < DOMAIN_ENTRIES_PER_L2_PAGETABLE; i++ ) + { + unsigned long gpte = l2_pgentry_val(gpl2e[i]); + unsigned long spte = l2_pgentry_val(spl2e[i]); + + check_pte( p, gpte, spte, 2, i ); + } + + + // go back and recurse + for ( i = 0; i < DOMAIN_ENTRIES_PER_L2_PAGETABLE; i++ ) + { + unsigned long gpte = l2_pgentry_val(gpl2e[i]); + unsigned long spte = l2_pgentry_val(spl2e[i]); + + if ( spte ) + check_l1_table( p, + i<<L2_PAGETABLE_SHIFT, + gpte>>PAGE_SHIFT, spte>>PAGE_SHIFT ); + + } + + unmap_domain_mem( spl2e ); + unmap_domain_mem( gpl2e ); + + SH_VVLOG("PT verified : l2_present = %d, l1_present = %d\n", + sh_l2_present, sh_l1_present ); + + return 1; +} + + +#endif + + + + + diff --git a/xen/include/asm-i386/config.h b/xen/include/asm-i386/config.h index 5c5fa8616b..3310934fe2 100644 --- a/xen/include/asm-i386/config.h +++ b/xen/include/asm-i386/config.h @@ -40,6 +40,7 @@ #define CONFIG_XEN_ATTENTION_KEY 1 + #define HZ 100 /* @@ -68,7 +69,7 @@ */ #define MAX_MONITOR_ADDRESS (16*1024*1024) #define MAX_DMA_ADDRESS (16*1024*1024) -#define MAX_DIRECTMAP_ADDRESS (44*1024*1024) +#define MAX_DIRECTMAP_ADDRESS (40*1024*1024) // XXX was 44 /* And the virtual addresses for the direct-map region... */ #define DIRECTMAP_VIRT_START (READONLY_MPT_VIRT_END) #define DIRECTMAP_VIRT_END (DIRECTMAP_VIRT_START + MAX_DIRECTMAP_ADDRESS) @@ -81,8 +82,11 @@ /* Next 4MB of virtual address space is used as a linear p.t. mapping. */ #define LINEAR_PT_VIRT_START (DIRECTMAP_VIRT_END) #define LINEAR_PT_VIRT_END (LINEAR_PT_VIRT_START + (4*1024*1024)) +/* Next 4MB of virtual address space is used as a shadow linear p.t. map. */ +#define SH_LINEAR_PT_VIRT_START (LINEAR_PT_VIRT_END) +#define SH_LINEAR_PT_VIRT_END (SH_LINEAR_PT_VIRT_START + (4*1024*1024)) /* Next 4MB of virtual address space used for per-domain mappings (eg. GDT). */ -#define PERDOMAIN_VIRT_START (LINEAR_PT_VIRT_END) +#define PERDOMAIN_VIRT_START (SH_LINEAR_PT_VIRT_END) #define PERDOMAIN_VIRT_END (PERDOMAIN_VIRT_START + (4*1024*1024)) #define GDT_VIRT_START (PERDOMAIN_VIRT_START) #define GDT_VIRT_END (GDT_VIRT_START + (64*1024)) diff --git a/xen/include/asm-i386/page.h b/xen/include/asm-i386/page.h index be860c32cd..1f8260e03c 100644 --- a/xen/include/asm-i386/page.h +++ b/xen/include/asm-i386/page.h @@ -91,6 +91,7 @@ typedef struct { unsigned long pt_lo; } pagetable_t; #include <asm/flushtlb.h> #define linear_pg_table ((l1_pgentry_t *)LINEAR_PT_VIRT_START) +#define linear_l2_table ((l2_pgentry_t *)(LINEAR_PT_VIRT_START+(LINEAR_PT_VIRT_START>>(L2_PAGETABLE_SHIFT-L1_PAGETABLE_SHIFT)))) extern l2_pgentry_t idle_pg_table[ENTRIES_PER_L2_PAGETABLE]; extern void paging_init(void); diff --git a/xen/include/asm-i386/processor.h b/xen/include/asm-i386/processor.h index 083a416a6f..08685b65a0 100644 --- a/xen/include/asm-i386/processor.h +++ b/xen/include/asm-i386/processor.h @@ -12,6 +12,7 @@ #include <asm/cpufeature.h> #include <asm/desc.h> #include <xen/config.h> +#include <xen/spinlock.h> #include <hypervisor-ifs/hypervisor-if.h> struct task_struct; @@ -415,6 +416,16 @@ struct mm_struct { */ l1_pgentry_t *perdomain_pt; pagetable_t pagetable; + + unsigned int shadow_mode; /* flags to control shadow table operation */ + pagetable_t shadow_table; + spinlock_t shadow_lock; + struct shadow_status *shadow_ht; + struct shadow_status *shadow_ht_free; + struct shadow_status *shadow_ht_extras; // extra allocation units + unsigned int shadow_page_count; + unsigned int shadow_max_page_count; + /* Current LDT details. */ unsigned long ldt_base, ldt_ents, shadow_ldt_mapcnt; /* Next entry is passed to LGDT on domain switch. */ diff --git a/xen/include/xen/mm.h b/xen/include/xen/mm.h index b24412a3de..bc5a6362ea 100644 --- a/xen/include/xen/mm.h +++ b/xen/include/xen/mm.h @@ -100,6 +100,7 @@ struct pfn_info /* 28-bit count of references to this frame. */ #define PGC_count_mask ((1<<28)-1) + /* We trust the slab allocator in slab.c, and our use of it. */ #define PageSlab(page) (1) #define PageSetSlab(page) ((void)0) diff --git a/xen/include/xen/perfc.h b/xen/include/xen/perfc.h index ad0b53eeb6..0f84c266dc 100644 --- a/xen/include/xen/perfc.h +++ b/xen/include/xen/perfc.h @@ -11,6 +11,11 @@ * PERFCOUNTER_CPU (counter, string, size) define a counter per CPU * PERFCOUNTER_ARRY (counter, string, size) define an array of counters * + * unlike "COUNTERS", "STATUS" variables DO NOT RESET + * PERFSTATUS (counter, string) define a new performance stauts + * PERFSTATUS_CPU (counter, string, size) define a status var per CPU + * PERFSTATUS_ARRY (counter, string, size) define an array of status vars + * * unsigned long perfc_value (counter) get value of a counter * unsigned long perfc_valuec (counter) get value of a per CPU counter * unsigned long perfc_valuea (counter, index) get value of an array counter @@ -32,6 +37,12 @@ atomic_t var[NR_CPUS]; #define PERFCOUNTER_ARRAY( var, name, size ) \ atomic_t var[size]; +#define PERFSTATUS( var, name ) \ + atomic_t var[1]; +#define PERFSTATUS_CPU( var, name ) \ + atomic_t var[NR_CPUS]; +#define PERFSTATUS_ARRAY( var, name, size ) \ + atomic_t var[size]; struct perfcounter_t { @@ -47,6 +58,7 @@ extern struct perfcounter_t perfcounters; #define perfc_setc(x,v) atomic_set(&perfcounters.x[smp_processor_id()], v) #define perfc_seta(x,y,v) atomic_set(&perfcounters.x[y], v) #define perfc_incr(x) atomic_inc(&perfcounters.x[0]) +#define perfc_decr(x) atomic_dec(&perfcounters.x[0]) #define perfc_incrc(x) atomic_inc(&perfcounters.x[smp_processor_id()]) #define perfc_incra(x,y) atomic_inc(&perfcounters.x[y]) #define perfc_add(x,y) atomic_add((y), &perfcounters.x[0]) diff --git a/xen/include/xen/perfc_defn.h b/xen/include/xen/perfc_defn.h index f81b5bcba1..bf06719e35 100644 --- a/xen/include/xen/perfc_defn.h +++ b/xen/include/xen/perfc_defn.h @@ -19,6 +19,17 @@ PERFCOUNTER_CPU( need_flush_tlb_flush, "PG_need_flush tlb flushes" ) PERFCOUNTER_CPU( calls_to_mmu_update, "calls_to_mmu_update" ) PERFCOUNTER_CPU( num_page_updates, "num_page_updates" ) - - - +PERFCOUNTER_CPU( calls_to_update_va, "calls_to_update_va_map" ) +PERFCOUNTER_CPU( page_faults, "page faults" ) +PERFCOUNTER_CPU( copy_user_faults, "copy_user faults" ) +PERFCOUNTER_CPU( map_domain_mem_count, "map_domain_mem count" ) + +PERFCOUNTER_CPU( shadow_l2_table_count, "shadow_l2_table count" ) +PERFCOUNTER_CPU( shadow_l1_table_count, "shadow_l1_table count" ) +PERFCOUNTER_CPU( unshadow_table_count, "unshadow_table count" ) +PERFCOUNTER_CPU( shadow_fixup_count, "shadow_fixup count" ) +PERFCOUNTER_CPU( shadow_update_va_fail, "shadow_update_va_fail" ) + +/* STATUS counters do not reset when 'P' is hit */ +PERFSTATUS( shadow_l2_pages, "current # shadow L2 pages" ) +PERFSTATUS( shadow_l1_pages, "current # shadow L1 pages" ) diff --git a/xen/include/xeno/shadow.h b/xen/include/xeno/shadow.h new file mode 100644 index 0000000000..212a0dbfbb --- /dev/null +++ b/xen/include/xeno/shadow.h @@ -0,0 +1,344 @@ +/* -*- Mode:C; c-basic-offset:4; tab-width:4 -*- */ + +#ifndef _XENO_SHADOW_H +#define _XENO_SHADOW_H + +#include <xeno/config.h> +#include <xeno/types.h> +#include <xeno/mm.h> +#include <xeno/perfc.h> + +/* Shadow PT flag bits in pfn_info */ +#define PSH_shadowed (1<<31) /* page has a shadow. PFN points to shadow */ +#define PSH_pending (1<<29) /* page is in the process of being shadowed */ +#define PSH_pfn_mask ((1<<21)-1) + +/* Shadow PT operation mode : shadowmode variable in mm_struct */ +#define SHM_test (1<<0) /* just run domain on shadow PTs */ +#define SHM_logdirty (1<<1) /* log pages that are dirtied */ +#define SHM_cow (1<<2) /* copy on write all dirtied pages */ +#define SHM_translate (1<<3) /* lookup machine pages in translation table */ + +#define shadow_linear_pg_table ((l1_pgentry_t *)SH_LINEAR_PT_VIRT_START) +#define shadow_linear_l2_table ((l2_pgentry_t *)(SH_LINEAR_PT_VIRT_START+(SH_LINEAR_PT_VIRT_START>>(L2_PAGETABLE_SHIFT-L1_PAGETABLE_SHIFT)))) + +extern pagetable_t shadow_mk_pagetable( struct task_struct *p, + unsigned long gptbase); +extern int shadow_fault( unsigned long va, long error_code ); +extern void shadow_l1_normal_pt_update( unsigned long pa, unsigned long gpte, + unsigned long *prev_spfn_ptr, + l1_pgentry_t **prev_spl1e_ptr ); +extern void shadow_l2_normal_pt_update( unsigned long pa, unsigned long gpte ); +extern void unshadow_table( unsigned long gpfn, unsigned int type ); +extern int shadow_mode_enable( struct task_struct *p, unsigned int mode ); + +#define SHADOW_DEBUG 0 +#define SHADOW_HASH_DEBUG 0 +#define SHADOW_OPTIMISE 1 + +struct shadow_status { + unsigned long pfn; // gpfn + unsigned long spfn_and_flags; // spfn plus flags + struct shadow_status *next; // use pull-to-front list. +}; + +#define shadow_ht_extra_size 128 /*128*/ +#define shadow_ht_buckets 256 /*256*/ + +#ifndef NDEBUG +#define SH_LOG(_f, _a...) \ + printk("DOM%llu: (file=shadow.c, line=%d) " _f "\n", \ + current->domain , __LINE__ , ## _a ) +#else +#define SH_LOG(_f, _a...) +#endif + +#if SHADOW_DEBUG +#define SH_VLOG(_f, _a...) \ + printk("DOM%llu: (file=shadow.c, line=%d) " _f "\n", \ + current->domain , __LINE__ , ## _a ) +#else +#define SH_VLOG(_f, _a...) +#endif + +#if 0 +#define SH_VVLOG(_f, _a...) \ + printk("DOM%llu: (file=shadow.c, line=%d) " _f "\n", \ + current->domain , __LINE__ , ## _a ) +#else +#define SH_VVLOG(_f, _a...) +#endif + + + +#if SHADOW_HASH_DEBUG +static void shadow_audit(struct task_struct *p, int print) +{ + int live=0, free=0, j=0, abs; + struct shadow_status *a; + + for(j=0;j<shadow_ht_buckets;j++) + { + a = &p->mm.shadow_ht[j]; + if(a->pfn) live++; + while(a->next && live<9999) + { + live++; + if(a->pfn == 0) + { + printk("XXX live=%d pfn=%08lx sp=%08lx next=%p\n", + live, a->pfn, a->spfn_and_flags, a->next); + BUG(); + } + a=a->next; + } + ASSERT(live<9999); + } + + a = p->mm.shadow_ht_free; + while(a) { free++; a=a->next; } + + if(print) printk("live=%d free=%d\n",live,free); + + abs=(perfc_value(shadow_l1_pages)+perfc_value(shadow_l2_pages))-live; + if( abs < -1 || abs > 1 ) + { + printk("live=%d free=%d l1=%d l2=%d\n",live,free, + perfc_value(shadow_l1_pages), perfc_value(shadow_l2_pages) ); + BUG(); + } + +} + +#else +#define shadow_audit(p, print) +#endif + +static inline struct shadow_status* hash_bucket( struct task_struct *p, + unsigned int gpfn ) +{ + return &(p->mm.shadow_ht[gpfn % shadow_ht_buckets]); +} + + +static inline unsigned long __shadow_status( struct task_struct *p, + unsigned int gpfn ) +{ + struct shadow_status **ob, *b, *B = hash_bucket( p, gpfn ); + + b = B; + ob = NULL; + + SH_VVLOG("lookup gpfn=%08lx bucket=%08lx", gpfn, b ); + shadow_audit(p,0); // if in debug mode + + do + { + if ( b->pfn == gpfn ) + { + unsigned long t; + struct shadow_status *x; + + // swap with head + t=B->pfn; B->pfn=b->pfn; b->pfn=t; + t=B->spfn_and_flags; B->spfn_and_flags=b->spfn_and_flags; + b->spfn_and_flags=t; + + if(ob) + { // pull to front + *ob=b->next; + x=B->next; + B->next=b; + b->next=x; + } + return B->spfn_and_flags; + } +#if SHADOW_HASH_DEBUG + else + { + if(b!=B)ASSERT(b->pfn); + } +#endif + ob=&b->next; + b=b->next; + } + while (b); + + return 0; +} + +/* we can make this locking more fine grained e.g. per shadow page if it +ever becomes a problem, but since we need a spin lock on the hash table +anyway its probably not worth being too clever. */ + +static inline unsigned long get_shadow_status( struct task_struct *p, + unsigned int gpfn ) +{ + unsigned long res; + + spin_lock(&p->mm.shadow_lock); + res = __shadow_status( p, gpfn ); + if (!res) spin_unlock(&p->mm.shadow_lock); + return res; +} + + +static inline void put_shadow_status( struct task_struct *p ) +{ + spin_unlock(&p->mm.shadow_lock); +} + + +static inline void delete_shadow_status( struct task_struct *p, + unsigned int gpfn ) +{ + struct shadow_status *b, *B, **ob; + + B = b = hash_bucket( p, gpfn ); + + SH_VVLOG("delete gpfn=%08x bucket=%p", gpfn, b ); + shadow_audit(p,0); + ASSERT(gpfn); + + if( b->pfn == gpfn ) + { + if (b->next) + { + struct shadow_status *D=b->next; + b->spfn_and_flags = b->next->spfn_and_flags; + b->pfn = b->next->pfn; + + b->next = b->next->next; + D->next = p->mm.shadow_ht_free; + p->mm.shadow_ht_free = D; + } + else + { + b->pfn = 0; + b->spfn_and_flags = 0; + } + +#if SHADOW_HASH_DEBUG + if( __shadow_status(p,gpfn) ) BUG(); +#endif + return; + } + + ob = &b->next; + b=b->next; + + do + { + if ( b->pfn == gpfn ) + { + b->pfn = 0; + b->spfn_and_flags = 0; + + // b is in the list + *ob=b->next; + b->next = p->mm.shadow_ht_free; + p->mm.shadow_ht_free = b; + +#if SHADOW_HASH_DEBUG + if( __shadow_status(p,gpfn) ) BUG(); +#endif + return; + } + + ob = &b->next; + b=b->next; + } + while (b); + + // if we got here, it wasn't in the list + BUG(); +} + + +static inline void set_shadow_status( struct task_struct *p, + unsigned int gpfn, unsigned long s ) +{ + struct shadow_status *b, *B, *extra, **fptr; + int i; + + B = b = hash_bucket( p, gpfn ); + + ASSERT(gpfn); + ASSERT(s); + SH_VVLOG("set gpfn=%08x s=%08lx bucket=%p(%p)", gpfn, s, b, b->next ); + shadow_audit(p,0); + + do + { + if ( b->pfn == gpfn ) + { + b->spfn_and_flags = s; + return; + } + + b=b->next; + } + while (b); + + // if we got here, this is an insert rather than update + + ASSERT( s ); // deletes must have succeeded by here + + if ( B->pfn == 0 ) + { + // we can use this head + ASSERT( B->next == 0 ); + B->pfn = gpfn; + B->spfn_and_flags = s; + return; + } + + if( unlikely(p->mm.shadow_ht_free == NULL) ) + { + SH_LOG("allocate more shadow hashtable blocks"); + + // we need to allocate more space + extra = kmalloc( sizeof(void*) + (shadow_ht_extra_size * + sizeof(struct shadow_status)), GFP_KERNEL ); + + if( ! extra ) BUG(); // should be more graceful here.... + + memset( extra, 0, sizeof(void*) + (shadow_ht_extra_size * + sizeof(struct shadow_status)) ); + + // add extras to free list + fptr = &p->mm.shadow_ht_free; + for ( i=0; i<shadow_ht_extra_size; i++ ) + { + *fptr = &extra[i]; + fptr = &(extra[i].next); + } + *fptr = NULL; + + *((struct shadow_status ** ) &p->mm.shadow_ht[shadow_ht_extra_size]) = + p->mm.shadow_ht_extras; + p->mm.shadow_ht_extras = extra; + + } + + // should really put this in B to go right to front + b = p->mm.shadow_ht_free; + p->mm.shadow_ht_free = b->next; + b->spfn_and_flags = s; + b->pfn = gpfn; + b->next = B->next; + B->next = b; + + return; +} + + + +#if SHADOW_DEBUG +extern int check_pagetable( struct task_struct *p, pagetable_t pt, char *s ); +#else +#define check_pagetable( p, pt, s ) +#endif + + +#endif diff --git a/xen/net/dev.c b/xen/net/dev.c index 05d474f98b..e7e277f5e5 100644 --- a/xen/net/dev.c +++ b/xen/net/dev.c @@ -28,6 +28,7 @@ #include <xen/init.h> #include <xen/module.h> #include <xen/event.h> +#include <xen/shadow.h> #include <asm/domain_page.h> #include <asm/pgalloc.h> #include <asm/io.h> @@ -488,11 +489,12 @@ struct netif_rx_stats netdev_rx_stat[NR_CPUS]; void deliver_packet(struct sk_buff *skb, net_vif_t *vif) { rx_shadow_entry_t *rx; - unsigned long *ptep, pte; + unsigned long *ptep, pte, new_pte; struct pfn_info *old_page, *new_page, *pte_page; unsigned short size; unsigned char offset, status = RING_STATUS_OK; struct task_struct *p = vif->domain; + unsigned long spte_pfn; memcpy(skb->mac.ethernet->h_dest, vif->vmac, ETH_ALEN); if ( ntohs(skb->mac.ethernet->h_proto) == ETH_P_ARP ) @@ -530,10 +532,12 @@ void deliver_packet(struct sk_buff *skb, net_vif_t *vif) wmb(); /* Get type count and set flush bit before updating PTE. */ pte = *ptep; + + new_pte = (pte & ~PAGE_MASK) | _PAGE_RW | _PAGE_PRESENT | + ((new_page - frame_table) << PAGE_SHIFT); + if ( unlikely(pte & _PAGE_PRESENT) || - unlikely(cmpxchg(ptep, pte, - (pte & ~PAGE_MASK) | _PAGE_RW | _PAGE_PRESENT | - ((new_page - frame_table) << PAGE_SHIFT))) != pte ) + unlikely(cmpxchg(ptep, pte, new_pte)) != pte ) { DPRINTK("PTE was modified or reused! %08lx %08lx\n", pte, *ptep); unmap_domain_mem(ptep); @@ -543,6 +547,19 @@ void deliver_packet(struct sk_buff *skb, net_vif_t *vif) goto out; } + if ( p->mm.shadow_mode && + (spte_pfn=get_shadow_status(p, pte_page-frame_table)) ) + { + unsigned long *sptr = map_domain_mem( (spte_pfn<<PAGE_SHIFT) | + (((unsigned long)ptep)&~PAGE_MASK) ); + + // avoid the fault later + *sptr = new_pte; + + unmap_domain_mem(sptr); + put_shadow_status(p); + } + machine_to_phys_mapping[new_page - frame_table] = machine_to_phys_mapping[old_page - frame_table]; @@ -2049,7 +2066,7 @@ static void get_rx_bufs(net_vif_t *vif) rx_shadow_entry_t *srx; unsigned long pte_pfn, buf_pfn; struct pfn_info *pte_page, *buf_page; - unsigned long *ptep, pte; + unsigned long *ptep, pte, spfn; spin_lock(&vif->rx_lock); @@ -2068,6 +2085,8 @@ static void get_rx_bufs(net_vif_t *vif) pte_pfn = rx.addr >> PAGE_SHIFT; pte_page = &frame_table[pte_pfn]; + + //printk("MMM %08lx ", rx.addr); /* The address passed down must be to a valid PTE. */ if ( unlikely(pte_pfn >= max_page) || @@ -2081,7 +2100,7 @@ static void get_rx_bufs(net_vif_t *vif) ptep = map_domain_mem(rx.addr); pte = *ptep; - + //printk("%08lx\n",pte); /* We must be passed a valid writeable mapping to swizzle. */ if ( unlikely((pte & (_PAGE_PRESENT|_PAGE_RW)) != (_PAGE_PRESENT|_PAGE_RW)) || @@ -2092,6 +2111,17 @@ static void get_rx_bufs(net_vif_t *vif) make_rx_response(vif, rx.id, 0, RING_STATUS_BAD_PAGE, 0); goto rx_unmap_and_continue; } + + if ( p->mm.shadow_mode && + (spfn=get_shadow_status(p, rx.addr>>PAGE_SHIFT)) ) + { + unsigned long * sptr = + map_domain_mem( (spfn<<PAGE_SHIFT) | (rx.addr&~PAGE_MASK) ); + + *sptr = 0; + unmap_domain_mem( sptr ); + put_shadow_status(p); + } buf_pfn = pte >> PAGE_SHIFT; buf_page = &frame_table[buf_pfn]; @@ -2112,6 +2142,8 @@ static void get_rx_bufs(net_vif_t *vif) put_page_and_type(pte_page); make_rx_response(vif, rx.id, 0, RING_STATUS_BAD_PAGE, 0); goto rx_unmap_and_continue; + + // XXX IAP should SHADOW_CONFIG do something here? } /* |