aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoriap10@tetris.cl.cam.ac.uk <iap10@tetris.cl.cam.ac.uk>2004-03-25 12:37:30 +0000
committeriap10@tetris.cl.cam.ac.uk <iap10@tetris.cl.cam.ac.uk>2004-03-25 12:37:30 +0000
commit3edb6b4a07f3b5e8628accd97e20ace4cf8ceb4a (patch)
tree99339d353e2acc57c74ee7c33d7cc35c65efe4f9
parent163ce6261c54cbfe6fec6f011497a3d14d30b5e4 (diff)
parent1cfe846da9267b5ee87813bb9e44d2a0a8ebaa12 (diff)
downloadxen-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--.rootkeys2
-rw-r--r--BitKeeper/etc/ignore558
-rw-r--r--xen/arch/i386/domain_page.c2
-rw-r--r--xen/arch/i386/process.c10
-rw-r--r--xen/arch/i386/traps.c12
-rw-r--r--xen/common/debug.c6
-rw-r--r--xen/common/domain.c19
-rw-r--r--xen/common/kernel.c23
-rw-r--r--xen/common/memory.c117
-rw-r--r--xen/common/perfc.c43
-rw-r--r--xen/common/shadow.c793
-rw-r--r--xen/include/asm-i386/config.h8
-rw-r--r--xen/include/asm-i386/page.h1
-rw-r--r--xen/include/asm-i386/processor.h11
-rw-r--r--xen/include/xen/mm.h1
-rw-r--r--xen/include/xen/perfc.h12
-rw-r--r--xen/include/xen/perfc_defn.h17
-rw-r--r--xen/include/xeno/shadow.h344
-rw-r--r--xen/net/dev.c44
19 files changed, 1978 insertions, 45 deletions
diff --git a/.rootkeys b/.rootkeys
index e61ecf8776..b8b93e6cc9 100644
--- a/.rootkeys
+++ b/.rootkeys
@@ -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(&current->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(&current->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(&current->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(&current->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(&current->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?
}
/*