3e5a4e683HKVU-sxtagrDasRB8eBVw linux-2.4.29-xen-sparse/mm/swapfile.c
41180721bNns9Na7w1nJ0ZVt8bhUNA linux-2.4.29-xen-sparse/mm/vmalloc.c
41505c57WAd5l1rlfCLNSCpx9J13vA linux-2.4.29-xen-sparse/net/core/skbuff.c
- 40f562372u3A7_kfbYYixPHJJxYUxA linux-2.6.10-xen-sparse/arch/xen/Kconfig
- 40f56237utH41NPukqHksuNf29IC9A linux-2.6.10-xen-sparse/arch/xen/Kconfig.drivers
- 40f56237penAAlWVBVDpeQZNFIg8CA linux-2.6.10-xen-sparse/arch/xen/Makefile
- 40f56237JTc60m1FRlUxkUaGSQKrNw linux-2.6.10-xen-sparse/arch/xen/boot/Makefile
- 40f56237hRxbacU_3PdoAl6DjZ3Jnw linux-2.6.10-xen-sparse/arch/xen/configs/xen0_defconfig
- 40f56237wubfjJKlfIzZlI3ZM2VgGA linux-2.6.10-xen-sparse/arch/xen/configs/xenU_defconfig
- 40f56237Mta0yHNaMS_qtM2rge0qYA linux-2.6.10-xen-sparse/arch/xen/i386/Kconfig
- 40f56238u2CJdXNpjsZgHBxeVyY-2g linux-2.6.10-xen-sparse/arch/xen/i386/Makefile
- 40f56238eczveJ86k_4hNxCLRQIF-g linux-2.6.10-xen-sparse/arch/xen/i386/kernel/Makefile
- 40f56238rXVTJQKbBuXXLH52qEArcg linux-2.6.10-xen-sparse/arch/xen/i386/kernel/cpu/Makefile
- 40f562385s4lr6Zg92gExe7UQ4A76Q linux-2.6.10-xen-sparse/arch/xen/i386/kernel/cpu/common.c
- 41ab440bnpxZdWShZrGgM9pPaz5rmA linux-2.6.10-xen-sparse/arch/xen/i386/kernel/cpu/mtrr/Makefile
- 41ab440bBKWz-aEOEojU4PAMXe3Ppg linux-2.6.10-xen-sparse/arch/xen/i386/kernel/cpu/mtrr/main.c
- 40f56238XDtHSijkAFlbv1PT8Bhw_Q linux-2.6.10-xen-sparse/arch/xen/i386/kernel/entry.S
- 40f56238bnvciAuyzAiMkdzGErYt1A linux-2.6.10-xen-sparse/arch/xen/i386/kernel/head.S
- 40f58a0d31M2EkuPbG94ns_nOi0PVA linux-2.6.10-xen-sparse/arch/xen/i386/kernel/i386_ksyms.c
- 40faa751_zbZlAmLyQgCXdYekVFdWA linux-2.6.10-xen-sparse/arch/xen/i386/kernel/ioport.c
- 40f56238ue3YRsK52HG7iccNzP1AwQ linux-2.6.10-xen-sparse/arch/xen/i386/kernel/ldt.c
- 41d54a76YMCA67S8J-TBT3J62Wx6yA linux-2.6.10-xen-sparse/arch/xen/i386/kernel/microcode.c
- 4107adf1cNtsuOxOB4T6paAoY2R2PA linux-2.6.10-xen-sparse/arch/xen/i386/kernel/pci-dma.c
- 40f56238a8iOVDEoostsbun_sy2i4g linux-2.6.10-xen-sparse/arch/xen/i386/kernel/process.c
- 40f56238YQIJoYG2ehDGEcdTgLmGbg linux-2.6.10-xen-sparse/arch/xen/i386/kernel/setup.c
- 40f56238nWMQg7CKbyTy0KJNvCzbtg linux-2.6.10-xen-sparse/arch/xen/i386/kernel/signal.c
- 40f56238qVGkpO_ycnQA8k03kQzAgA linux-2.6.10-xen-sparse/arch/xen/i386/kernel/time.c
- 40f56238NzTgeO63RGoxHrW5NQeO3Q linux-2.6.10-xen-sparse/arch/xen/i386/kernel/timers/Makefile
- 40f56238BMqG5PuSHufpjbvp_helBw linux-2.6.10-xen-sparse/arch/xen/i386/kernel/timers/timer_tsc.c
- 40f562389xNa78YBZciUibQjyRU_Lg linux-2.6.10-xen-sparse/arch/xen/i386/kernel/traps.c
- 40f56238JypKAUG01ZojFwH7qnZ5uA linux-2.6.10-xen-sparse/arch/xen/i386/kernel/vsyscall.S
- 40f56238wi6AdNQjm0RT57bSkwb6hg linux-2.6.10-xen-sparse/arch/xen/i386/kernel/vsyscall.lds
- 40f56238a3w6-byOzexIlMgni76Lcg linux-2.6.10-xen-sparse/arch/xen/i386/mm/Makefile
- 40f56238ILx8xlbywNbzTdv5Zr4xXQ linux-2.6.10-xen-sparse/arch/xen/i386/mm/fault.c
- 4118cc35CbY8rfGVspF5O-7EkXBEAA linux-2.6.10-xen-sparse/arch/xen/i386/mm/highmem.c
- 40f562383SKvDStdtrvzr5fyCbW4rw linux-2.6.10-xen-sparse/arch/xen/i386/mm/hypervisor.c
- 40f56239xcNylAxuGsQHwi1AyMLV8w linux-2.6.10-xen-sparse/arch/xen/i386/mm/init.c
- 41062ab7CjxC1UBaFhOMWWdhHkIUyg linux-2.6.10-xen-sparse/arch/xen/i386/mm/ioremap.c
- 413b5ab8LIowAnQrEmaOJSdmqm96jQ linux-2.6.10-xen-sparse/arch/xen/i386/mm/pageattr.c
- 40f5623906UYHv1rsVUeRc0tFT0dWw linux-2.6.10-xen-sparse/arch/xen/i386/mm/pgtable.c
- 4107adf12ndy94MidCaivDibJ3pPAg linux-2.6.10-xen-sparse/arch/xen/i386/pci/Makefile
- 4107adf1WcCgkhsdLTRGX52cOG1vJg linux-2.6.10-xen-sparse/arch/xen/i386/pci/direct.c
- 4107adf1s5u6249DNPUViX1YNagbUQ linux-2.6.10-xen-sparse/arch/xen/i386/pci/irq.c
- 40f56239zOksGg_H4XD4ye6iZNtoZA linux-2.6.10-xen-sparse/arch/xen/kernel/Makefile
- 40f56239bvOjuuuViZ0XMlNiREFC0A linux-2.6.10-xen-sparse/arch/xen/kernel/ctrl_if.c
- 41ab6fa06JdF7jxUsuDcjN3UhuIAxg linux-2.6.10-xen-sparse/arch/xen/kernel/devmem.c
- 40f56238xFQe9T7M_U_FItM-bZIpLw linux-2.6.10-xen-sparse/arch/xen/kernel/evtchn.c
- 4110f478aeQWllIN7J4kouAHiAqrPw linux-2.6.10-xen-sparse/arch/xen/kernel/fixup.c
- 412dfae9eA3_6e6bCGUtg1mj8b56fQ linux-2.6.10-xen-sparse/arch/xen/kernel/gnttab.c
- 40f562392LBhwmOxVPsYdkYXMxI_ZQ linux-2.6.10-xen-sparse/arch/xen/kernel/reboot.c
- 414c113396tK1HTVeUalm3u-1DF16g linux-2.6.10-xen-sparse/arch/xen/kernel/skbuff.c
- 3f68905c5eiA-lBMQSvXLMWS1ikDEA linux-2.6.10-xen-sparse/arch/xen/kernel/xen_proc.c
- 41261688yS8eAyy-7kzG4KBs0xbYCA linux-2.6.10-xen-sparse/drivers/Makefile
- 4108f5c1WfTIrs0HZFeV39sttekCTw linux-2.6.10-xen-sparse/drivers/char/mem.c
- 4111308bZAIzwf_Kzu6x1TZYZ3E0_Q linux-2.6.10-xen-sparse/drivers/char/tty_io.c
- 40f56239Dp_vMTgz8TEbvo1hjHGc3w linux-2.6.10-xen-sparse/drivers/xen/Makefile
- 41768fbcncpBQf8s2l2-CwoSNIZ9uA linux-2.6.10-xen-sparse/drivers/xen/balloon/Makefile
- 3e6377f8i5e9eGz7Pw6fQuhuTQ7DQg linux-2.6.10-xen-sparse/drivers/xen/balloon/balloon.c
- 410d0893otFGghmv4dUXDUBBdY5aIA linux-2.6.10-xen-sparse/drivers/xen/blkback/Makefile
- 4087cf0d1XgMkooTZAiJS6NrcpLQNQ linux-2.6.10-xen-sparse/drivers/xen/blkback/blkback.c
- 4087cf0dZadZ8r6CEt4fNN350Yle3A linux-2.6.10-xen-sparse/drivers/xen/blkback/common.h
- 4087cf0dxlh29iw0w-9rxOCEGCjPcw linux-2.6.10-xen-sparse/drivers/xen/blkback/control.c
- 4087cf0dbuoH20fMjNZjcgrRK-1msQ linux-2.6.10-xen-sparse/drivers/xen/blkback/interface.c
- 4087cf0dk97tacDzxfByWV7JifUYqA linux-2.6.10-xen-sparse/drivers/xen/blkback/vbd.c
- 40f56239Sfle6wGv5FS0wjS_HI150A linux-2.6.10-xen-sparse/drivers/xen/blkfront/Kconfig
- 40f562395atl9x4suKGhPkjqLOXESg linux-2.6.10-xen-sparse/drivers/xen/blkfront/Makefile
- 40f56239-JNIaTzlviVJohVdoYOUpw linux-2.6.10-xen-sparse/drivers/xen/blkfront/blkfront.c
- 40f56239y9naBTXe40Pi2J_z3p-d1g linux-2.6.10-xen-sparse/drivers/xen/blkfront/block.h
- 40f56239BVfPsXBiWQitXgDRtOsiqg linux-2.6.10-xen-sparse/drivers/xen/blkfront/vbd.c
- 40f56239fsLjvtD8YBRAWphps4FDjg linux-2.6.10-xen-sparse/drivers/xen/console/Makefile
- 3e5a4e651TH-SXHoufurnWjgl5bfOA linux-2.6.10-xen-sparse/drivers/xen/console/console.c
- 40f56239KYxO0YabhPzCTeUuln-lnA linux-2.6.10-xen-sparse/drivers/xen/evtchn/Makefile
- 40f56239DoibTX6R-ZYd3QTXAB8_TA linux-2.6.10-xen-sparse/drivers/xen/evtchn/evtchn.c
- 410a9817HEVJvred5Oy_uKH3HFJC5Q linux-2.6.10-xen-sparse/drivers/xen/netback/Makefile
- 4097ba831lpGeLlPg-bfV8XarVVuoQ linux-2.6.10-xen-sparse/drivers/xen/netback/common.h
- 4097ba83wvv8yi5P5xugCUBAdb6O-A linux-2.6.10-xen-sparse/drivers/xen/netback/control.c
- 4097ba83byY5bTSugJGZ1exTxIcMKw linux-2.6.10-xen-sparse/drivers/xen/netback/interface.c
- 4087cf0dGmSbFhFZyIZBJzvqxY-qBw linux-2.6.10-xen-sparse/drivers/xen/netback/netback.c
- 40f56239lrg_Ob0BJ8WBFS1zeg2CYw linux-2.6.10-xen-sparse/drivers/xen/netfront/Kconfig
- 40f56239Wd4k_ycG_mFsSO1r5xKdtQ linux-2.6.10-xen-sparse/drivers/xen/netfront/Makefile
- 405853f6nbeazrNyEWNHBuoSg2PiPA linux-2.6.10-xen-sparse/drivers/xen/netfront/netfront.c
- 4108f5c1ppFXVpQzCOAZ6xXYubsjKA linux-2.6.10-xen-sparse/drivers/xen/privcmd/Makefile
- 3e5a4e65IUfzzMu2kZFlGEB8-rpTaA linux-2.6.10-xen-sparse/drivers/xen/privcmd/privcmd.c
- 412f47e4RKD-R5IS5gEXvcT8L4v8gA linux-2.6.10-xen-sparse/include/asm-generic/pgtable.h
- 40f56239YAjS52QG2FIAQpHDZAdGHg linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/desc.h
- 4107adf1E5O4ztGHNGMzCCNhcvqNow linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/dma-mapping.h
- 40f5623akIoBsQ3KxSB2kufkbgONXQ linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/fixmap.h
- 41979925z1MsKU1SfuuheM1IFDQ_bA linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/floppy.h
- 4118b6a418gnL6AZsTdglC92YGqYTg linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/highmem.h
- 40f5623aJVXQwpJMOLE99XgvGsfQ8Q linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/io.h
- 40f5623aKXkBBxgpLx2NcvkncQ1Yyw linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/mach-xen/irq_vectors.h
- 40f5623aDMCsWOFO0jktZ4e8sjwvEg linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/mach-xen/setup_arch_post.h
- 40f5623arsFXkGdPvIqvFi3yFXGR0Q linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/mach-xen/setup_arch_pre.h
- 4120f807GCO0uqsLqdZj9csxR1Wthw linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/mmu_context.h
- 40f5623aFTyFTR-vdiA-KaGxk5JOKQ linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/msr.h
- 40f5623adgjZq9nAgCt0IXdWl7udSA linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/page.h
- 40f5623a54NuG-7qHihGYmw4wWQnMA linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/param.h
- 41137cc1kkvg0cg7uxddcEfjL7L67w linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/pci.h
- 40f5623atCokYc2uCysSJ8jFO8TEsw linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/pgalloc.h
- 412e01beTwiaC8sYY4XJP8PxLST5CA linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/pgtable-2level-defs.h
- 40f5623aEToIXouJgO-ao5d5pcEt1w linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/pgtable-2level.h
- 40f5623aCCXRPlGpNthVXstGz9ZV3A linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/pgtable.h
- 40f5623aPCkQQfPtJSooGdhcatrvnQ linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/processor.h
- 412ea0afQL2CAI-f522TbLjLPMibPQ linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/ptrace.h
- 40f5623bzLvxr7WoJIxVf2OH4rCBJg linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/segment.h
- 40f5623bG_LzgG6-qwk292nTc5Wabw linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/setup.h
- 40f5623bgzm_9vwxpzJswlAxg298Gg linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/synch_bitops.h
- 40f5623bVdKP7Dt7qm8twu3NcnGNbA linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/system.h
- 40f5623bc8LKPRO09wY5dGDnY_YCpw linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/tlbflush.h
- 41062ab7uFxnCq-KtPeAm-aV8CicgA linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/vga.h
- 40f5623bxUbeGjkRrjDguCy_Gm8RLw linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/xor.h
- 41af4017PDMuSmMWtSRU5UC9Vylw5g linux-2.6.10-xen-sparse/include/asm-xen/balloon.h
- 40f5623bYNP7tHE2zX6YQxp9Zq2utQ linux-2.6.10-xen-sparse/include/asm-xen/ctrl_if.h
- 40f5623b3Eqs8pAc5WpPX8_jTzV2qw linux-2.6.10-xen-sparse/include/asm-xen/evtchn.h
- 419b4e9367PjTEvdjwavWN12BeBBXg linux-2.6.10-xen-sparse/include/asm-xen/foreign_page.h
- 412dfaeazclyNDM0cpnp60Yo4xulpQ linux-2.6.10-xen-sparse/include/asm-xen/gnttab.h
- 40f5623aGPlsm0u1LTO-NVZ6AGzNRQ linux-2.6.10-xen-sparse/include/asm-xen/hypervisor.h
- 3f108af1ylCIm82H052FVTfXACBHrw linux-2.6.10-xen-sparse/include/asm-xen/linux-public/privcmd.h
- 3fa8e3f0kBLeE4To2vpdi3cpJbIkbQ linux-2.6.10-xen-sparse/include/asm-xen/linux-public/suspend.h
- 40f5623cndVUFlkxpf7Lfx7xu8madQ linux-2.6.10-xen-sparse/include/asm-xen/multicall.h
- 4122466356eIBnC9ot44WSVVIFyhQA linux-2.6.10-xen-sparse/include/asm-xen/queues.h
- 3f689063BoW-HWV3auUJ-OqXfcGArw linux-2.6.10-xen-sparse/include/asm-xen/xen_proc.h
- 419b4e93z2S0gR17XTy8wg09JEwAhg linux-2.6.10-xen-sparse/include/linux/gfp.h
+42305f545Vc5SLCUewZ2-n-P9JJhEQ linux-2.6.10-xen-sparse/include/linux/highmem.h
- 419dfc609zbti8rqL60tL2dHXQ_rvQ linux-2.6.10-xen-sparse/include/linux/irq.h
- 4124f66f4NaKNa0xPiGGykn9QaZk3w linux-2.6.10-xen-sparse/include/linux/skbuff.h
- 419dfc6awx7w88wk6cG9P3mPidX6LQ linux-2.6.10-xen-sparse/kernel/irq/manage.c
- 40f56a0ddHCSs3501MY4hRf22tctOw linux-2.6.10-xen-sparse/mkbuildtree
+42305f54Q6xJ1bXcQJlCQq1m-e2C8g linux-2.6.10-xen-sparse/mm/highmem.c
- 412f46c0LJuKAgSPGoC0Z1DEkLfuLA linux-2.6.10-xen-sparse/mm/memory.c
- 410a94a4KT6I6X0LVc7djB39tRDp4g linux-2.6.10-xen-sparse/mm/page_alloc.c
- 41505c572m-s9ATiO1LiD1GPznTTIg linux-2.6.10-xen-sparse/net/core/skbuff.c
+ 40f562372u3A7_kfbYYixPHJJxYUxA linux-2.6.11-xen-sparse/arch/xen/Kconfig
+ 40f56237utH41NPukqHksuNf29IC9A linux-2.6.11-xen-sparse/arch/xen/Kconfig.drivers
+ 40f56237penAAlWVBVDpeQZNFIg8CA linux-2.6.11-xen-sparse/arch/xen/Makefile
+ 40f56237JTc60m1FRlUxkUaGSQKrNw linux-2.6.11-xen-sparse/arch/xen/boot/Makefile
+ 40f56237hRxbacU_3PdoAl6DjZ3Jnw linux-2.6.11-xen-sparse/arch/xen/configs/xen0_defconfig
+ 40f56237wubfjJKlfIzZlI3ZM2VgGA linux-2.6.11-xen-sparse/arch/xen/configs/xenU_defconfig
+ 40f56237Mta0yHNaMS_qtM2rge0qYA linux-2.6.11-xen-sparse/arch/xen/i386/Kconfig
+ 40f56238u2CJdXNpjsZgHBxeVyY-2g linux-2.6.11-xen-sparse/arch/xen/i386/Makefile
+ 40f56238eczveJ86k_4hNxCLRQIF-g linux-2.6.11-xen-sparse/arch/xen/i386/kernel/Makefile
+ 40f56238rXVTJQKbBuXXLH52qEArcg linux-2.6.11-xen-sparse/arch/xen/i386/kernel/cpu/Makefile
+ 40f562385s4lr6Zg92gExe7UQ4A76Q linux-2.6.11-xen-sparse/arch/xen/i386/kernel/cpu/common.c
+ 41ab440bnpxZdWShZrGgM9pPaz5rmA linux-2.6.11-xen-sparse/arch/xen/i386/kernel/cpu/mtrr/Makefile
+ 41ab440bBKWz-aEOEojU4PAMXe3Ppg linux-2.6.11-xen-sparse/arch/xen/i386/kernel/cpu/mtrr/main.c
+ 40f56238XDtHSijkAFlbv1PT8Bhw_Q linux-2.6.11-xen-sparse/arch/xen/i386/kernel/entry.S
+ 40f56238bnvciAuyzAiMkdzGErYt1A linux-2.6.11-xen-sparse/arch/xen/i386/kernel/head.S
+ 40f58a0d31M2EkuPbG94ns_nOi0PVA linux-2.6.11-xen-sparse/arch/xen/i386/kernel/i386_ksyms.c
+ 40faa751_zbZlAmLyQgCXdYekVFdWA linux-2.6.11-xen-sparse/arch/xen/i386/kernel/ioport.c
+ 40f56238ue3YRsK52HG7iccNzP1AwQ linux-2.6.11-xen-sparse/arch/xen/i386/kernel/ldt.c
+ 41d54a76YMCA67S8J-TBT3J62Wx6yA linux-2.6.11-xen-sparse/arch/xen/i386/kernel/microcode.c
+ 4107adf1cNtsuOxOB4T6paAoY2R2PA linux-2.6.11-xen-sparse/arch/xen/i386/kernel/pci-dma.c
+ 40f56238a8iOVDEoostsbun_sy2i4g linux-2.6.11-xen-sparse/arch/xen/i386/kernel/process.c
+ 40f56238YQIJoYG2ehDGEcdTgLmGbg linux-2.6.11-xen-sparse/arch/xen/i386/kernel/setup.c
+ 40f56238nWMQg7CKbyTy0KJNvCzbtg linux-2.6.11-xen-sparse/arch/xen/i386/kernel/signal.c
+ 40f56238qVGkpO_ycnQA8k03kQzAgA linux-2.6.11-xen-sparse/arch/xen/i386/kernel/time.c
+ 40f56238NzTgeO63RGoxHrW5NQeO3Q linux-2.6.11-xen-sparse/arch/xen/i386/kernel/timers/Makefile
+ 40f56238BMqG5PuSHufpjbvp_helBw linux-2.6.11-xen-sparse/arch/xen/i386/kernel/timers/timer_tsc.c
+ 40f562389xNa78YBZciUibQjyRU_Lg linux-2.6.11-xen-sparse/arch/xen/i386/kernel/traps.c
+ 40f56238JypKAUG01ZojFwH7qnZ5uA linux-2.6.11-xen-sparse/arch/xen/i386/kernel/vsyscall.S
+ 40f56238wi6AdNQjm0RT57bSkwb6hg linux-2.6.11-xen-sparse/arch/xen/i386/kernel/vsyscall.lds
+ 40f56238a3w6-byOzexIlMgni76Lcg linux-2.6.11-xen-sparse/arch/xen/i386/mm/Makefile
+ 40f56238ILx8xlbywNbzTdv5Zr4xXQ linux-2.6.11-xen-sparse/arch/xen/i386/mm/fault.c
+ 4118cc35CbY8rfGVspF5O-7EkXBEAA linux-2.6.11-xen-sparse/arch/xen/i386/mm/highmem.c
+ 40f562383SKvDStdtrvzr5fyCbW4rw linux-2.6.11-xen-sparse/arch/xen/i386/mm/hypervisor.c
+ 40f56239xcNylAxuGsQHwi1AyMLV8w linux-2.6.11-xen-sparse/arch/xen/i386/mm/init.c
+ 41062ab7CjxC1UBaFhOMWWdhHkIUyg linux-2.6.11-xen-sparse/arch/xen/i386/mm/ioremap.c
+ 413b5ab8LIowAnQrEmaOJSdmqm96jQ linux-2.6.11-xen-sparse/arch/xen/i386/mm/pageattr.c
+ 40f5623906UYHv1rsVUeRc0tFT0dWw linux-2.6.11-xen-sparse/arch/xen/i386/mm/pgtable.c
+ 4107adf12ndy94MidCaivDibJ3pPAg linux-2.6.11-xen-sparse/arch/xen/i386/pci/Makefile
+ 4107adf1WcCgkhsdLTRGX52cOG1vJg linux-2.6.11-xen-sparse/arch/xen/i386/pci/direct.c
+ 4107adf1s5u6249DNPUViX1YNagbUQ linux-2.6.11-xen-sparse/arch/xen/i386/pci/irq.c
+ 40f56239zOksGg_H4XD4ye6iZNtoZA linux-2.6.11-xen-sparse/arch/xen/kernel/Makefile
+ 40f56239bvOjuuuViZ0XMlNiREFC0A linux-2.6.11-xen-sparse/arch/xen/kernel/ctrl_if.c
+ 41ab6fa06JdF7jxUsuDcjN3UhuIAxg linux-2.6.11-xen-sparse/arch/xen/kernel/devmem.c
+ 40f56238xFQe9T7M_U_FItM-bZIpLw linux-2.6.11-xen-sparse/arch/xen/kernel/evtchn.c
+ 4110f478aeQWllIN7J4kouAHiAqrPw linux-2.6.11-xen-sparse/arch/xen/kernel/fixup.c
+ 412dfae9eA3_6e6bCGUtg1mj8b56fQ linux-2.6.11-xen-sparse/arch/xen/kernel/gnttab.c
+ 40f562392LBhwmOxVPsYdkYXMxI_ZQ linux-2.6.11-xen-sparse/arch/xen/kernel/reboot.c
+ 414c113396tK1HTVeUalm3u-1DF16g linux-2.6.11-xen-sparse/arch/xen/kernel/skbuff.c
+ 3f68905c5eiA-lBMQSvXLMWS1ikDEA linux-2.6.11-xen-sparse/arch/xen/kernel/xen_proc.c
+ 41261688yS8eAyy-7kzG4KBs0xbYCA linux-2.6.11-xen-sparse/drivers/Makefile
+ 4108f5c1WfTIrs0HZFeV39sttekCTw linux-2.6.11-xen-sparse/drivers/char/mem.c
+ 4111308bZAIzwf_Kzu6x1TZYZ3E0_Q linux-2.6.11-xen-sparse/drivers/char/tty_io.c
+ 40f56239Dp_vMTgz8TEbvo1hjHGc3w linux-2.6.11-xen-sparse/drivers/xen/Makefile
+ 41768fbcncpBQf8s2l2-CwoSNIZ9uA linux-2.6.11-xen-sparse/drivers/xen/balloon/Makefile
+ 3e6377f8i5e9eGz7Pw6fQuhuTQ7DQg linux-2.6.11-xen-sparse/drivers/xen/balloon/balloon.c
+ 410d0893otFGghmv4dUXDUBBdY5aIA linux-2.6.11-xen-sparse/drivers/xen/blkback/Makefile
+ 4087cf0d1XgMkooTZAiJS6NrcpLQNQ linux-2.6.11-xen-sparse/drivers/xen/blkback/blkback.c
+ 4087cf0dZadZ8r6CEt4fNN350Yle3A linux-2.6.11-xen-sparse/drivers/xen/blkback/common.h
+ 4087cf0dxlh29iw0w-9rxOCEGCjPcw linux-2.6.11-xen-sparse/drivers/xen/blkback/control.c
+ 4087cf0dbuoH20fMjNZjcgrRK-1msQ linux-2.6.11-xen-sparse/drivers/xen/blkback/interface.c
+ 4087cf0dk97tacDzxfByWV7JifUYqA linux-2.6.11-xen-sparse/drivers/xen/blkback/vbd.c
+ 40f56239Sfle6wGv5FS0wjS_HI150A linux-2.6.11-xen-sparse/drivers/xen/blkfront/Kconfig
+ 40f562395atl9x4suKGhPkjqLOXESg linux-2.6.11-xen-sparse/drivers/xen/blkfront/Makefile
+ 40f56239-JNIaTzlviVJohVdoYOUpw linux-2.6.11-xen-sparse/drivers/xen/blkfront/blkfront.c
+ 40f56239y9naBTXe40Pi2J_z3p-d1g linux-2.6.11-xen-sparse/drivers/xen/blkfront/block.h
+ 40f56239BVfPsXBiWQitXgDRtOsiqg linux-2.6.11-xen-sparse/drivers/xen/blkfront/vbd.c
+ 40f56239fsLjvtD8YBRAWphps4FDjg linux-2.6.11-xen-sparse/drivers/xen/console/Makefile
+ 3e5a4e651TH-SXHoufurnWjgl5bfOA linux-2.6.11-xen-sparse/drivers/xen/console/console.c
+ 40f56239KYxO0YabhPzCTeUuln-lnA linux-2.6.11-xen-sparse/drivers/xen/evtchn/Makefile
+ 40f56239DoibTX6R-ZYd3QTXAB8_TA linux-2.6.11-xen-sparse/drivers/xen/evtchn/evtchn.c
+ 410a9817HEVJvred5Oy_uKH3HFJC5Q linux-2.6.11-xen-sparse/drivers/xen/netback/Makefile
+ 4097ba831lpGeLlPg-bfV8XarVVuoQ linux-2.6.11-xen-sparse/drivers/xen/netback/common.h
+ 4097ba83wvv8yi5P5xugCUBAdb6O-A linux-2.6.11-xen-sparse/drivers/xen/netback/control.c
+ 4097ba83byY5bTSugJGZ1exTxIcMKw linux-2.6.11-xen-sparse/drivers/xen/netback/interface.c
+ 4087cf0dGmSbFhFZyIZBJzvqxY-qBw linux-2.6.11-xen-sparse/drivers/xen/netback/netback.c
+ 40f56239lrg_Ob0BJ8WBFS1zeg2CYw linux-2.6.11-xen-sparse/drivers/xen/netfront/Kconfig
+ 40f56239Wd4k_ycG_mFsSO1r5xKdtQ linux-2.6.11-xen-sparse/drivers/xen/netfront/Makefile
+ 405853f6nbeazrNyEWNHBuoSg2PiPA linux-2.6.11-xen-sparse/drivers/xen/netfront/netfront.c
+ 4108f5c1ppFXVpQzCOAZ6xXYubsjKA linux-2.6.11-xen-sparse/drivers/xen/privcmd/Makefile
+ 3e5a4e65IUfzzMu2kZFlGEB8-rpTaA linux-2.6.11-xen-sparse/drivers/xen/privcmd/privcmd.c
+ 412f47e4RKD-R5IS5gEXvcT8L4v8gA linux-2.6.11-xen-sparse/include/asm-generic/pgtable.h
+ 40f56239YAjS52QG2FIAQpHDZAdGHg linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/desc.h
+ 4107adf1E5O4ztGHNGMzCCNhcvqNow linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/dma-mapping.h
+ 40f5623akIoBsQ3KxSB2kufkbgONXQ linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/fixmap.h
+ 41979925z1MsKU1SfuuheM1IFDQ_bA linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/floppy.h
+ 4118b6a418gnL6AZsTdglC92YGqYTg linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/highmem.h
+ 40f5623aJVXQwpJMOLE99XgvGsfQ8Q linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/io.h
+ 40f5623aKXkBBxgpLx2NcvkncQ1Yyw linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/mach-xen/irq_vectors.h
+ 40f5623aDMCsWOFO0jktZ4e8sjwvEg linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/mach-xen/setup_arch_post.h
+ 40f5623arsFXkGdPvIqvFi3yFXGR0Q linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/mach-xen/setup_arch_pre.h
+ 4120f807GCO0uqsLqdZj9csxR1Wthw linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/mmu_context.h
+ 40f5623aFTyFTR-vdiA-KaGxk5JOKQ linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/msr.h
+ 40f5623adgjZq9nAgCt0IXdWl7udSA linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/page.h
+ 40f5623a54NuG-7qHihGYmw4wWQnMA linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/param.h
+ 41137cc1kkvg0cg7uxddcEfjL7L67w linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/pci.h
+ 40f5623atCokYc2uCysSJ8jFO8TEsw linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/pgalloc.h
+ 412e01beTwiaC8sYY4XJP8PxLST5CA linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/pgtable-2level-defs.h
+ 40f5623aEToIXouJgO-ao5d5pcEt1w linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/pgtable-2level.h
+ 40f5623aCCXRPlGpNthVXstGz9ZV3A linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/pgtable.h
+ 40f5623aPCkQQfPtJSooGdhcatrvnQ linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/processor.h
+ 412ea0afQL2CAI-f522TbLjLPMibPQ linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/ptrace.h
+ 40f5623bzLvxr7WoJIxVf2OH4rCBJg linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/segment.h
+ 40f5623bG_LzgG6-qwk292nTc5Wabw linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/setup.h
+ 40f5623bgzm_9vwxpzJswlAxg298Gg linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/synch_bitops.h
+ 40f5623bVdKP7Dt7qm8twu3NcnGNbA linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/system.h
+ 40f5623bc8LKPRO09wY5dGDnY_YCpw linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/tlbflush.h
+ 41062ab7uFxnCq-KtPeAm-aV8CicgA linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/vga.h
+ 40f5623bxUbeGjkRrjDguCy_Gm8RLw linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/xor.h
+ 41af4017PDMuSmMWtSRU5UC9Vylw5g linux-2.6.11-xen-sparse/include/asm-xen/balloon.h
+ 40f5623bYNP7tHE2zX6YQxp9Zq2utQ linux-2.6.11-xen-sparse/include/asm-xen/ctrl_if.h
+ 40f5623b3Eqs8pAc5WpPX8_jTzV2qw linux-2.6.11-xen-sparse/include/asm-xen/evtchn.h
+ 419b4e9367PjTEvdjwavWN12BeBBXg linux-2.6.11-xen-sparse/include/asm-xen/foreign_page.h
+ 412dfaeazclyNDM0cpnp60Yo4xulpQ linux-2.6.11-xen-sparse/include/asm-xen/gnttab.h
+ 40f5623aGPlsm0u1LTO-NVZ6AGzNRQ linux-2.6.11-xen-sparse/include/asm-xen/hypervisor.h
+ 3f108af1ylCIm82H052FVTfXACBHrw linux-2.6.11-xen-sparse/include/asm-xen/linux-public/privcmd.h
+ 3fa8e3f0kBLeE4To2vpdi3cpJbIkbQ linux-2.6.11-xen-sparse/include/asm-xen/linux-public/suspend.h
+ 40f5623cndVUFlkxpf7Lfx7xu8madQ linux-2.6.11-xen-sparse/include/asm-xen/multicall.h
+ 4122466356eIBnC9ot44WSVVIFyhQA linux-2.6.11-xen-sparse/include/asm-xen/queues.h
+ 3f689063BoW-HWV3auUJ-OqXfcGArw linux-2.6.11-xen-sparse/include/asm-xen/xen_proc.h
+ 419b4e93z2S0gR17XTy8wg09JEwAhg linux-2.6.11-xen-sparse/include/linux/gfp.h
+ 419dfc609zbti8rqL60tL2dHXQ_rvQ linux-2.6.11-xen-sparse/include/linux/irq.h
+ 419dfc6awx7w88wk6cG9P3mPidX6LQ linux-2.6.11-xen-sparse/kernel/irq/manage.c
+ 40f56a0ddHCSs3501MY4hRf22tctOw linux-2.6.11-xen-sparse/mkbuildtree
+ 412f46c0LJuKAgSPGoC0Z1DEkLfuLA linux-2.6.11-xen-sparse/mm/memory.c
+ 410a94a4KT6I6X0LVc7djB39tRDp4g linux-2.6.11-xen-sparse/mm/page_alloc.c
413cb1e4zst25MDYjg63Y-NGC5_pLg netbsd-2.0-xen-sparse/Makefile
413cb1e5c_Mkxf_X0zimEhTKI_l4DA netbsd-2.0-xen-sparse/mkbuildtree
413cb1e5kY_Zil7-b0kI6hvCIxBEYg netbsd-2.0-xen-sparse/nbconfig-xen
--- /dev/null
- phys_to_machine_mapping[pfn] = INVALID_P2M_ENTRY;
+ /******************************************************************************
+ * balloon.c
+ *
+ * Xen balloon driver - enables returning/claiming memory to/from Xen.
+ *
+ * Copyright (c) 2003, B Dragovic
+ * Copyright (c) 2003-2004, M Williamson, K Fraser
+ *
+ * This file may be distributed separately from the Linux kernel, or
+ * incorporated into other software packages, subject to the following license:
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this source file (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy, modify,
+ * merge, publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+ #include <linux/config.h>
+ #include <linux/kernel.h>
+ #include <linux/module.h>
+ #include <linux/sched.h>
+ #include <linux/errno.h>
+ #include <linux/mm.h>
+ #include <linux/mman.h>
+ #include <linux/smp_lock.h>
+ #include <linux/pagemap.h>
+ #include <linux/bootmem.h>
+ #include <linux/highmem.h>
+ #include <linux/vmalloc.h>
+ #include <asm-xen/xen_proc.h>
+ #include <asm-xen/hypervisor.h>
+ #include <asm-xen/ctrl_if.h>
+ #include <asm-xen/balloon.h>
+ #include <asm/pgalloc.h>
+ #include <asm/pgtable.h>
+ #include <asm/uaccess.h>
+ #include <asm/tlb.h>
+ #include <linux/list.h>
+
+ static struct proc_dir_entry *balloon_pde;
+
+ static DECLARE_MUTEX(balloon_mutex);
+ spinlock_t balloon_lock = SPIN_LOCK_UNLOCKED;
+
+ /* We aim for 'current allocation' == 'target allocation'. */
+ static unsigned long current_pages;
+ static unsigned long target_pages;
+
+ /* We may hit the hard limit in Xen. If we do then we remember it. */
+ static unsigned long hard_limit;
+
+ /*
+ * Drivers may alter the memory reservation independently, but they must
+ * inform the balloon driver so that we can avoid hitting the hard limit.
+ */
+ static unsigned long driver_pages;
+
+ /* List of ballooned pages, threaded through the mem_map array. */
+ static LIST_HEAD(ballooned_pages);
+ static unsigned long balloon_low, balloon_high;
+
+ /* Main work function, always executed in process context. */
+ static void balloon_process(void *unused);
+ static DECLARE_WORK(balloon_worker, balloon_process, NULL);
+ static struct timer_list balloon_timer;
+
+ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+ /* Use the private and mapping fields of struct page as a list. */
+ #define PAGE_TO_LIST(p) ( (struct list_head *)&p->private )
+ #define LIST_TO_PAGE(l) ( list_entry( ((unsigned long *)l), \
+ struct page, private ) )
+ #define UNLIST_PAGE(p) do { list_del(PAGE_TO_LIST(p)); \
+ p->mapping = NULL; \
+ p->private = 0; } while(0)
+ #else
+ /* There's a dedicated list field in struct page we can use. */
+ #define PAGE_TO_LIST(p) ( &p->list )
+ #define LIST_TO_PAGE(l) ( list_entry(l, struct page, list) )
+ #define UNLIST_PAGE(p) ( list_del(&p->list) )
+ #define pte_offset_kernel pte_offset
+ #define subsys_initcall(_fn) __initcall(_fn)
++#define pfn_to_page(_pfn) (mem_map + (_pfn))
+ #endif
+
+ #define IPRINTK(fmt, args...) \
+ printk(KERN_INFO "xen_mem: " fmt, ##args)
+ #define WPRINTK(fmt, args...) \
+ printk(KERN_WARNING "xen_mem: " fmt, ##args)
+
+ /* balloon_append: add the given page to the balloon. */
+ static void balloon_append(struct page *page)
+ {
+ /* Low memory is re-populated first, so highmem pages go at list tail. */
+ if ( PageHighMem(page) )
+ {
+ list_add_tail(PAGE_TO_LIST(page), &ballooned_pages);
+ balloon_high++;
+ }
+ else
+ {
+ list_add(PAGE_TO_LIST(page), &ballooned_pages);
+ balloon_low++;
+ }
+ }
+
+ /* balloon_retrieve: rescue a page from the balloon, if it is not empty. */
+ static struct page *balloon_retrieve(void)
+ {
+ struct page *page;
+
+ if ( list_empty(&ballooned_pages) )
+ return NULL;
+
+ page = LIST_TO_PAGE(ballooned_pages.next);
+ UNLIST_PAGE(page);
+
+ if ( PageHighMem(page) )
+ balloon_high--;
+ else
+ balloon_low--;
+
+ return page;
+ }
+
+ static inline pte_t *get_ptep(unsigned long addr)
+ {
+ pgd_t *pgd;
+ pud_t *pud;
+ pmd_t *pmd;
+
+ pgd = pgd_offset_k(addr);
+ if ( pgd_none(*pgd) || pgd_bad(*pgd) ) BUG();
+
+ pud = pud_offset(pgd, addr);
+ if ( pud_none(*pud) || pud_bad(*pud) ) BUG();
+
+ pmd = pmd_offset(pud, addr);
+ if ( pmd_none(*pmd) || pmd_bad(*pmd) ) BUG();
+
+ return pte_offset_kernel(pmd, addr);
+ }
+
+ static void balloon_alarm(unsigned long unused)
+ {
+ schedule_work(&balloon_worker);
+ }
+
+ static unsigned long current_target(void)
+ {
+ unsigned long target = min(target_pages, hard_limit);
+ if ( target > (current_pages + balloon_low + balloon_high) )
+ target = current_pages + balloon_low + balloon_high;
+ return target;
+ }
+
+ /*
+ * We avoid multiple worker processes conflicting via the balloon mutex.
+ * We may of course race updates of the target counts (which are protected
+ * by the balloon lock), or with changes to the Xen hard limit, but we will
+ * recover from these in time.
+ */
+ static void balloon_process(void *unused)
+ {
+ unsigned long *mfn_list, pfn, i, flags;
+ struct page *page;
+ long credit, debt, rc;
+ void *v;
+
+ down(&balloon_mutex);
+
+ retry:
+ mfn_list = NULL;
+
+ if ( (credit = current_target() - current_pages) > 0 )
+ {
+ mfn_list = (unsigned long *)vmalloc(credit * sizeof(*mfn_list));
+ if ( mfn_list == NULL )
+ goto out;
+
+ balloon_lock(flags);
+ rc = HYPERVISOR_dom_mem_op(
+ MEMOP_increase_reservation, mfn_list, credit, 0);
+ balloon_unlock(flags);
+ if ( rc < credit )
+ {
+ /* We hit the Xen hard limit: reprobe. */
+ if ( HYPERVISOR_dom_mem_op(
+ MEMOP_decrease_reservation, mfn_list, rc, 0) != rc )
+ BUG();
+ hard_limit = current_pages + rc - driver_pages;
+ vfree(mfn_list);
+ goto retry;
+ }
+
+ for ( i = 0; i < credit; i++ )
+ {
+ if ( (page = balloon_retrieve()) == NULL )
+ BUG();
+
+ pfn = page - mem_map;
+ if ( phys_to_machine_mapping[pfn] != INVALID_P2M_ENTRY )
+ BUG();
+
+ /* Update P->M and M->P tables. */
+ phys_to_machine_mapping[pfn] = mfn_list[i];
+ queue_machphys_update(mfn_list[i], pfn);
+
+ /* Link back into the page tables if it's not a highmem page. */
+ if ( pfn < max_low_pfn )
+ queue_l1_entry_update(
+ get_ptep((unsigned long)__va(pfn << PAGE_SHIFT)),
+ (mfn_list[i] << PAGE_SHIFT) | pgprot_val(PAGE_KERNEL));
+
+ /* Finally, relinquish the memory back to the system allocator. */
+ ClearPageReserved(page);
+ set_page_count(page, 1);
+ __free_page(page);
+ }
+
+ current_pages += credit;
+ }
+ else if ( credit < 0 )
+ {
+ debt = -credit;
+
+ mfn_list = (unsigned long *)vmalloc(debt * sizeof(*mfn_list));
+ if ( mfn_list == NULL )
+ goto out;
+
+ for ( i = 0; i < debt; i++ )
+ {
+ if ( (page = alloc_page(GFP_HIGHUSER)) == NULL )
+ {
+ debt = i;
+ break;
+ }
+
+ pfn = page - mem_map;
+ mfn_list[i] = phys_to_machine_mapping[pfn];
- v = phys_to_virt((page - mem_map) << PAGE_SHIFT);
+
+ if ( !PageHighMem(page) )
+ {
-#endif
-
- balloon_append(page);
++ v = phys_to_virt(pfn << PAGE_SHIFT);
+ scrub_pages(v, 1);
+ queue_l1_entry_update(get_ptep((unsigned long)v), 0);
+ }
+ #ifdef CONFIG_XEN_SCRUB_PAGES
+ else
+ {
+ v = kmap(page);
+ scrub_pages(v, 1);
+ kunmap(page);
+ }
++#endif
+ }
+
++ /* Ensure that ballooned highmem pages don't have cached mappings. */
++ kmap_flush_unused();
++
+ /* Flush updates through and flush the TLB. */
+ xen_tlb_flush();
+
++ /* No more mappings: invalidate pages in P2M and add to balloon. */
++ for ( i = 0; i < debt; i++ )
++ {
++ pfn = mfn_to_pfn(mfn_list[i]);
++ phys_to_machine_mapping[pfn] = INVALID_P2M_ENTRY;
++ balloon_append(pfn_to_page(pfn));
++ }
++
+ if ( HYPERVISOR_dom_mem_op(
+ MEMOP_decrease_reservation, mfn_list, debt, 0) != debt )
+ BUG();
+
+ current_pages -= debt;
+ }
+
+ out:
+ if ( mfn_list != NULL )
+ vfree(mfn_list);
+
+ /* Schedule more work if there is some still to be done. */
+ if ( current_target() != current_pages )
+ mod_timer(&balloon_timer, jiffies + HZ);
+
+ up(&balloon_mutex);
+ }
+
+ /* Resets the Xen limit, sets new target, and kicks off processing. */
+ static void set_new_target(unsigned long target)
+ {
+ /* No need for lock. Not read-modify-write updates. */
+ hard_limit = ~0UL;
+ target_pages = target;
+ schedule_work(&balloon_worker);
+ }
+
+ static void balloon_ctrlif_rx(ctrl_msg_t *msg, unsigned long id)
+ {
+ switch ( msg->subtype )
+ {
+ case CMSG_MEM_REQUEST_SET:
+ {
+ mem_request_t *req = (mem_request_t *)&msg->msg[0];
+ if ( msg->length != sizeof(mem_request_t) )
+ goto parse_error;
+ set_new_target(req->target);
+ req->status = 0;
+ }
+ break;
+ default:
+ goto parse_error;
+ }
+
+ ctrl_if_send_response(msg);
+ return;
+
+ parse_error:
+ msg->length = 0;
+ ctrl_if_send_response(msg);
+ }
+
+ static int balloon_write(struct file *file, const char __user *buffer,
+ unsigned long count, void *data)
+ {
+ char memstring[64], *endchar;
+ unsigned long long target_bytes;
+
+ if ( !capable(CAP_SYS_ADMIN) )
+ return -EPERM;
+
+ if ( count <= 1 )
+ return -EBADMSG; /* runt */
+ if ( count > sizeof(memstring) )
+ return -EFBIG; /* too long */
+
+ if ( copy_from_user(memstring, buffer, count) )
+ return -EFAULT;
+ memstring[sizeof(memstring)-1] = '\0';
+
+ target_bytes = memparse(memstring, &endchar);
+ set_new_target(target_bytes >> PAGE_SHIFT);
+
+ return count;
+ }
+
+ static int balloon_read(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
+ {
+ int len;
+
+ #define K(_p) ((_p)<<(PAGE_SHIFT-10))
+ len = sprintf(
+ page,
+ "Current allocation: %8lu kB\n"
+ "Requested target: %8lu kB\n"
+ "Low-mem balloon: %8lu kB\n"
+ "High-mem balloon: %8lu kB\n"
+ "Xen hard limit: ",
+ K(current_pages), K(target_pages), K(balloon_low), K(balloon_high));
+
+ if ( hard_limit != ~0UL )
+ len += sprintf(
+ page + len,
+ "%8lu kB (inc. %8lu kB driver headroom)\n",
+ K(hard_limit), K(driver_pages));
+ else
+ len += sprintf(
+ page + len,
+ " ??? kB\n");
+
+ *eof = 1;
+ return len;
+ }
+
+ static int __init balloon_init(void)
+ {
+ unsigned long pfn;
+ struct page *page;
+
+ IPRINTK("Initialising balloon driver.\n");
+
+ current_pages = min(xen_start_info.nr_pages, max_pfn);
+ target_pages = current_pages;
+ balloon_low = 0;
+ balloon_high = 0;
+ driver_pages = 0UL;
+ hard_limit = ~0UL;
+
+ init_timer(&balloon_timer);
+ balloon_timer.data = 0;
+ balloon_timer.function = balloon_alarm;
+
+ if ( (balloon_pde = create_xen_proc_entry("balloon", 0644)) == NULL )
+ {
+ WPRINTK("Unable to create /proc/xen/balloon.\n");
+ return -1;
+ }
+
+ balloon_pde->read_proc = balloon_read;
+ balloon_pde->write_proc = balloon_write;
+
+ (void)ctrl_if_register_receiver(CMSG_MEM_REQUEST, balloon_ctrlif_rx, 0);
+
+ /* Initialise the balloon with excess memory space. */
+ for ( pfn = xen_start_info.nr_pages; pfn < max_pfn; pfn++ )
+ {
+ page = &mem_map[pfn];
+ if ( !PageReserved(page) )
+ balloon_append(page);
+ }
+
+ return 0;
+ }
+
+ subsys_initcall(balloon_init);
+
+ void balloon_update_driver_allowance(long delta)
+ {
+ unsigned long flags;
+ balloon_lock(flags);
+ driver_pages += delta; /* non-atomic update */
+ balloon_unlock(flags);
+ }
+
+ void balloon_put_pages(unsigned long *mfn_list, unsigned long nr_mfns)
+ {
+ unsigned long flags;
+
+ balloon_lock(flags);
+ if ( HYPERVISOR_dom_mem_op(MEMOP_decrease_reservation,
+ mfn_list, nr_mfns, 0) != nr_mfns )
+ BUG();
+ current_pages -= nr_mfns; /* non-atomic update */
+ balloon_unlock(flags);
+
+ schedule_work(&balloon_worker);
+ }
+
+ EXPORT_SYMBOL(balloon_update_driver_allowance);
+ EXPORT_SYMBOL(balloon_put_pages);
--- /dev/null
- x->extent.device = grow->extent.device;
+ /******************************************************************************
+ * blkback/vbd.c
+ *
+ * Routines for managing virtual block devices (VBDs).
+ *
+ * NOTE: vbd_lock protects updates to the rb_tree against concurrent lookups
+ * in vbd_translate. All other lookups are implicitly protected because the
+ * only caller (the control message dispatch routine) serializes the calls.
+ *
+ * Copyright (c) 2003-2004, Keir Fraser & Steve Hand
+ */
+
+ #include "common.h"
+
+ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+ static dev_t vbd_map_devnum(blkif_pdev_t);
+ #endif
+
+ void vbd_create(blkif_be_vbd_create_t *create)
+ {
+ vbd_t *vbd;
+ rb_node_t **rb_p, *rb_parent = NULL;
+ blkif_t *blkif;
+ blkif_vdev_t vdevice = create->vdevice;
+
+ blkif = blkif_find_by_handle(create->domid, create->blkif_handle);
+ if ( unlikely(blkif == NULL) )
+ {
+ DPRINTK("vbd_create attempted for non-existent blkif (%u,%u)\n",
+ create->domid, create->blkif_handle);
+ create->status = BLKIF_BE_STATUS_INTERFACE_NOT_FOUND;
+ return;
+ }
+
+ rb_p = &blkif->vbd_rb.rb_node;
+ while ( *rb_p != NULL )
+ {
+ rb_parent = *rb_p;
+ vbd = rb_entry(rb_parent, vbd_t, rb);
+ if ( vdevice < vbd->vdevice )
+ {
+ rb_p = &rb_parent->rb_left;
+ }
+ else if ( vdevice > vbd->vdevice )
+ {
+ rb_p = &rb_parent->rb_right;
+ }
+ else
+ {
+ DPRINTK("vbd_create attempted for already existing vbd\n");
+ create->status = BLKIF_BE_STATUS_VBD_EXISTS;
+ return;
+ }
+ }
+
+ if ( unlikely((vbd = kmalloc(sizeof(vbd_t), GFP_KERNEL)) == NULL) )
+ {
+ DPRINTK("vbd_create: out of memory\n");
+ create->status = BLKIF_BE_STATUS_OUT_OF_MEMORY;
+ return;
+ }
+
+ vbd->vdevice = vdevice;
+ vbd->readonly = create->readonly;
+ vbd->type = VDISK_TYPE_DISK | VDISK_FLAG_VIRT;
+ vbd->extents = NULL;
+
+ spin_lock(&blkif->vbd_lock);
+ rb_link_node(&vbd->rb, rb_parent, rb_p);
+ rb_insert_color(&vbd->rb, &blkif->vbd_rb);
+ spin_unlock(&blkif->vbd_lock);
+
+ DPRINTK("Successful creation of vdev=%04x (dom=%u)\n",
+ vdevice, create->domid);
+ create->status = BLKIF_BE_STATUS_OKAY;
+ }
+
+
+ /* Grow a VBD by appending a new extent. Fails if the VBD doesn't exist. */
+ void vbd_grow(blkif_be_vbd_grow_t *grow)
+ {
+ blkif_t *blkif;
+ blkif_extent_le_t **px, *x;
+ vbd_t *vbd = NULL;
+ rb_node_t *rb;
+ blkif_vdev_t vdevice = grow->vdevice;
+ unsigned long sz;
+
+ blkif = blkif_find_by_handle(grow->domid, grow->blkif_handle);
+ if ( unlikely(blkif == NULL) )
+ {
+ DPRINTK("vbd_grow attempted for non-existent blkif (%u,%u)\n",
+ grow->domid, grow->blkif_handle);
+ grow->status = BLKIF_BE_STATUS_INTERFACE_NOT_FOUND;
+ return;
+ }
+
+ rb = blkif->vbd_rb.rb_node;
+ while ( rb != NULL )
+ {
+ vbd = rb_entry(rb, vbd_t, rb);
+ if ( vdevice < vbd->vdevice )
+ rb = rb->rb_left;
+ else if ( vdevice > vbd->vdevice )
+ rb = rb->rb_right;
+ else
+ break;
+ }
+
+ if ( unlikely(vbd == NULL) || unlikely(vbd->vdevice != vdevice) )
+ {
+ DPRINTK("vbd_grow: attempted to append extent to non-existent VBD.\n");
+ grow->status = BLKIF_BE_STATUS_VBD_NOT_FOUND;
+ return;
+ }
+
+ if ( grow->extent.sector_start > 0 )
+ {
+ DPRINTK("vbd_grow: dev %08x start not zero.\n", grow->extent.device);
+ grow->status = BLKIF_BE_STATUS_EXTENT_NOT_FOUND;
+ return;
+ }
+
+ if ( unlikely((x = kmalloc(sizeof(blkif_extent_le_t),
+ GFP_KERNEL)) == NULL) )
+ {
+ DPRINTK("vbd_grow: out of memory\n");
+ grow->status = BLKIF_BE_STATUS_OUT_OF_MEMORY;
+ return;
+ }
+
++ /* Mask to 16-bit for compatibility with old tools */
++ x->extent.device = grow->extent.device & 0xffff;
+ x->extent.sector_start = grow->extent.sector_start;
+ x->extent.sector_length = grow->extent.sector_length;
+ x->next = (blkif_extent_le_t *)NULL;
+
+ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+ x->bdev = open_by_devnum(vbd_map_devnum(x->extent.device),
+ vbd->readonly ? FMODE_READ : FMODE_WRITE);
+ if ( IS_ERR(x->bdev) )
+ {
+ DPRINTK("vbd_grow: device %08x doesn't exist.\n", x->extent.device);
+ grow->status = BLKIF_BE_STATUS_EXTENT_NOT_FOUND;
+ goto out;
+ }
+ /* XXXcl maybe bd_claim? */
+
+ if ( (x->bdev->bd_disk == NULL) )
+ {
+ DPRINTK("vbd_grow: device %08x doesn't exist.\n", x->extent.device);
+ grow->status = BLKIF_BE_STATUS_EXTENT_NOT_FOUND;
+ blkdev_put(x->bdev);
+ goto out;
+ }
+
+ /* get size in sectors */
+ if ( x->bdev->bd_part )
+ sz = x->bdev->bd_part->nr_sects;
+ else
+ sz = x->bdev->bd_disk->capacity;
+
+ #else
+ if( !blk_size[MAJOR(x->extent.device)] )
+ {
+ DPRINTK("vbd_grow: device %08x doesn't exist.\n", x->extent.device);
+ grow->status = BLKIF_BE_STATUS_EXTENT_NOT_FOUND;
+ goto out;
+ }
+
+ /* convert blocks (1KB) to sectors */
+ sz = blk_size[MAJOR(x->extent.device)][MINOR(x->extent.device)] * 2;
+
+ if ( sz == 0 )
+ {
+ DPRINTK("vbd_grow: device %08x zero size!\n", x->extent.device);
+ grow->status = BLKIF_BE_STATUS_EXTENT_NOT_FOUND;
+ goto out;
+ }
+ #endif
+
+ /*
+ * NB. This test assumes sector_start == 0, which is always the case
+ * in Xen 1.3. In fact the whole grow/shrink interface could do with
+ * some simplification.
+ */
+ if ( x->extent.sector_length > sz )
+ x->extent.sector_length = sz;
+
+ DPRINTK("vbd_grow: requested_len %llu actual_len %lu\n",
+ x->extent.sector_length, sz);
+
+ for ( px = &vbd->extents; *px != NULL; px = &(*px)->next )
+ continue;
+
+ *px = x; /* ATOMIC: no need for vbd_lock. */
+
+ DPRINTK("Successful grow of vdev=%04x (dom=%u)\n",
+ vdevice, grow->domid);
+
+ grow->status = BLKIF_BE_STATUS_OKAY;
+ return;
+
+ out:
+ kfree(x);
+ }
+
+
+ void vbd_shrink(blkif_be_vbd_shrink_t *shrink)
+ {
+ blkif_t *blkif;
+ blkif_extent_le_t **px, *x;
+ vbd_t *vbd = NULL;
+ rb_node_t *rb;
+ blkif_vdev_t vdevice = shrink->vdevice;
+
+ blkif = blkif_find_by_handle(shrink->domid, shrink->blkif_handle);
+ if ( unlikely(blkif == NULL) )
+ {
+ DPRINTK("vbd_shrink attempted for non-existent blkif (%u,%u)\n",
+ shrink->domid, shrink->blkif_handle);
+ shrink->status = BLKIF_BE_STATUS_INTERFACE_NOT_FOUND;
+ return;
+ }
+
+ rb = blkif->vbd_rb.rb_node;
+ while ( rb != NULL )
+ {
+ vbd = rb_entry(rb, vbd_t, rb);
+ if ( vdevice < vbd->vdevice )
+ rb = rb->rb_left;
+ else if ( vdevice > vbd->vdevice )
+ rb = rb->rb_right;
+ else
+ break;
+ }
+
+ if ( unlikely(vbd == NULL) || unlikely(vbd->vdevice != vdevice) )
+ {
+ shrink->status = BLKIF_BE_STATUS_VBD_NOT_FOUND;
+ return;
+ }
+
+ if ( unlikely(vbd->extents == NULL) )
+ {
+ shrink->status = BLKIF_BE_STATUS_EXTENT_NOT_FOUND;
+ return;
+ }
+
+ /* Find the last extent. We now know that there is at least one. */
+ for ( px = &vbd->extents; (*px)->next != NULL; px = &(*px)->next )
+ continue;
+
+ x = *px;
+ *px = x->next; /* ATOMIC: no need for vbd_lock. */
+
+ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+ blkdev_put(x->bdev);
+ #endif
+ kfree(x);
+
+ shrink->status = BLKIF_BE_STATUS_OKAY;
+ }
+
+
+ void vbd_destroy(blkif_be_vbd_destroy_t *destroy)
+ {
+ blkif_t *blkif;
+ vbd_t *vbd;
+ rb_node_t *rb;
+ blkif_extent_le_t *x, *t;
+ blkif_vdev_t vdevice = destroy->vdevice;
+
+ blkif = blkif_find_by_handle(destroy->domid, destroy->blkif_handle);
+ if ( unlikely(blkif == NULL) )
+ {
+ DPRINTK("vbd_destroy attempted for non-existent blkif (%u,%u)\n",
+ destroy->domid, destroy->blkif_handle);
+ destroy->status = BLKIF_BE_STATUS_INTERFACE_NOT_FOUND;
+ return;
+ }
+
+ rb = blkif->vbd_rb.rb_node;
+ while ( rb != NULL )
+ {
+ vbd = rb_entry(rb, vbd_t, rb);
+ if ( vdevice < vbd->vdevice )
+ rb = rb->rb_left;
+ else if ( vdevice > vbd->vdevice )
+ rb = rb->rb_right;
+ else
+ goto found;
+ }
+
+ destroy->status = BLKIF_BE_STATUS_VBD_NOT_FOUND;
+ return;
+
+ found:
+ spin_lock(&blkif->vbd_lock);
+ rb_erase(rb, &blkif->vbd_rb);
+ spin_unlock(&blkif->vbd_lock);
+
+ x = vbd->extents;
+ kfree(vbd);
+
+ while ( x != NULL )
+ {
+ t = x->next;
+ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+ blkdev_put(x->bdev);
+ #endif
+ kfree(x);
+ x = t;
+ }
+ }
+
+
+ void destroy_all_vbds(blkif_t *blkif)
+ {
+ vbd_t *vbd;
+ rb_node_t *rb;
+ blkif_extent_le_t *x, *t;
+
+ spin_lock(&blkif->vbd_lock);
+
+ while ( (rb = blkif->vbd_rb.rb_node) != NULL )
+ {
+ vbd = rb_entry(rb, vbd_t, rb);
+
+ rb_erase(rb, &blkif->vbd_rb);
+ x = vbd->extents;
+ kfree(vbd);
+
+ while ( x != NULL )
+ {
+ t = x->next;
+ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+ blkdev_put(x->bdev);
+ #endif
+ kfree(x);
+ x = t;
+ }
+ }
+
+ spin_unlock(&blkif->vbd_lock);
+ }
+
+
+ static int vbd_probe_single(blkif_t *blkif, vdisk_t *vbd_info, vbd_t *vbd)
+ {
+ blkif_extent_le_t *x;
+
+ vbd_info->device = vbd->vdevice;
+ vbd_info->info = vbd->type;
+ if ( vbd->readonly )
+ vbd_info->info |= VDISK_FLAG_RO;
+ vbd_info->capacity = 0ULL;
+ for ( x = vbd->extents; x != NULL; x = x->next )
+ vbd_info->capacity += x->extent.sector_length;
+
+ return 0;
+ }
+
+
+ int vbd_probe(blkif_t *blkif, vdisk_t *vbd_info, int max_vbds)
+ {
+ int rc = 0, nr_vbds = 0;
+ rb_node_t *rb;
+
+ spin_lock(&blkif->vbd_lock);
+
+ if ( (rb = blkif->vbd_rb.rb_node) == NULL )
+ goto out;
+
+ new_subtree:
+ /* STEP 1. Find least node (it'll be left-most). */
+ while ( rb->rb_left != NULL )
+ rb = rb->rb_left;
+
+ for ( ; ; )
+ {
+ /* STEP 2. Dealt with left subtree. Now process current node. */
+ if ( (rc = vbd_probe_single(blkif, &vbd_info[nr_vbds],
+ rb_entry(rb, vbd_t, rb))) != 0 )
+ goto out;
+ if ( ++nr_vbds == max_vbds )
+ goto out;
+
+ /* STEP 3. Process right subtree, if any. */
+ if ( rb->rb_right != NULL )
+ {
+ rb = rb->rb_right;
+ goto new_subtree;
+ }
+
+ /* STEP 4. Done both subtrees. Head back through ancesstors. */
+ for ( ; ; )
+ {
+ /* We're done when we get back to the root node. */
+ if ( rb->rb_parent == NULL )
+ goto out;
+ /* If we are left of parent, then parent is next to process. */
+ if ( rb->rb_parent->rb_left == rb )
+ break;
+ /* If we are right of parent, then we climb to grandparent. */
+ rb = rb->rb_parent;
+ }
+
+ rb = rb->rb_parent;
+ }
+
+ out:
+ spin_unlock(&blkif->vbd_lock);
+ return (rc == 0) ? nr_vbds : rc;
+ }
+
+
+ int vbd_translate(phys_seg_t *pseg, blkif_t *blkif, int operation)
+ {
+ blkif_extent_le_t *x;
+ vbd_t *vbd;
+ rb_node_t *rb;
+ blkif_sector_t sec_off;
+ unsigned long nr_secs;
+
+ /* Take the vbd_lock because another thread could be updating the tree. */
+ spin_lock(&blkif->vbd_lock);
+
+ rb = blkif->vbd_rb.rb_node;
+ while ( rb != NULL )
+ {
+ vbd = rb_entry(rb, vbd_t, rb);
+ if ( pseg->dev < vbd->vdevice )
+ rb = rb->rb_left;
+ else if ( pseg->dev > vbd->vdevice )
+ rb = rb->rb_right;
+ else
+ goto found;
+ }
+
+ DPRINTK("vbd_translate; domain %u attempted to access "
+ "non-existent VBD.\n", blkif->domid);
+
+ spin_unlock(&blkif->vbd_lock);
+ return -ENODEV;
+
+ found:
+
+ if ( (operation == WRITE) && vbd->readonly )
+ {
+ spin_unlock(&blkif->vbd_lock);
+ return -EACCES;
+ }
+
+ /*
+ * Now iterate through the list of blkif_extents, working out which should
+ * be used to perform the translation.
+ */
+ sec_off = pseg->sector_number;
+ nr_secs = pseg->nr_sects;
+ for ( x = vbd->extents; x != NULL; x = x->next )
+ {
+ if ( sec_off < x->extent.sector_length )
+ {
+ pseg->dev = x->extent.device;
+ pseg->bdev = x->bdev;
+ pseg->sector_number = x->extent.sector_start + sec_off;
+ if ( unlikely((sec_off + nr_secs) > x->extent.sector_length) )
+ goto overrun;
+ spin_unlock(&blkif->vbd_lock);
+ return 1;
+ }
+ sec_off -= x->extent.sector_length;
+ }
+
+ DPRINTK("vbd_translate: end of vbd.\n");
+ spin_unlock(&blkif->vbd_lock);
+ return -EACCES;
+
+ /*
+ * Here we deal with overrun onto the following extent. We don't deal with
+ * overrun of more than one boundary since each request is restricted to
+ * 2^9 512-byte sectors, so it should be trivial for control software to
+ * ensure that extents are large enough to prevent excessive overrun.
+ */
+ overrun:
+
+ /* Adjust length of first chunk to run to end of first extent. */
+ pseg[0].nr_sects = x->extent.sector_length - sec_off;
+
+ /* Set second chunk buffer and length to start where first chunk ended. */
+ pseg[1].buffer = pseg[0].buffer + (pseg[0].nr_sects << 9);
+ pseg[1].nr_sects = nr_secs - pseg[0].nr_sects;
+
+ /* Now move to the next extent. Check it exists and is long enough! */
+ if ( unlikely((x = x->next) == NULL) ||
+ unlikely(x->extent.sector_length < pseg[1].nr_sects) )
+ {
+ DPRINTK("vbd_translate: multiple overruns or end of vbd.\n");
+ spin_unlock(&blkif->vbd_lock);
+ return -EACCES;
+ }
+
+ /* Store the real device and start sector for the second chunk. */
+ pseg[1].dev = x->extent.device;
+ pseg[1].bdev = x->bdev;
+ pseg[1].sector_number = x->extent.sector_start;
+
+ spin_unlock(&blkif->vbd_lock);
+ return 2;
+ }
+
+
+ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+
+ #define MAJOR_XEN(dev) ((dev)>>8)
+ #define MINOR_XEN(dev) ((dev) & 0xff)
+
+ #ifndef FANCY_REMAPPING
+ static dev_t vbd_map_devnum(blkif_pdev_t cookie)
+ {
+ int major = MAJOR_XEN(cookie);
+ int minor = MINOR_XEN(cookie);
+
+ return MKDEV(major, minor);
+ }
+ #else
+ #define XEN_IDE0_MAJOR IDE0_MAJOR
+ #define XEN_IDE1_MAJOR IDE1_MAJOR
+ #define XEN_IDE2_MAJOR IDE2_MAJOR
+ #define XEN_IDE3_MAJOR IDE3_MAJOR
+ #define XEN_IDE4_MAJOR IDE4_MAJOR
+ #define XEN_IDE5_MAJOR IDE5_MAJOR
+ #define XEN_IDE6_MAJOR IDE6_MAJOR
+ #define XEN_IDE7_MAJOR IDE7_MAJOR
+ #define XEN_IDE8_MAJOR IDE8_MAJOR
+ #define XEN_IDE9_MAJOR IDE9_MAJOR
+ #define XEN_SCSI_DISK0_MAJOR SCSI_DISK0_MAJOR
+ #define XEN_SCSI_DISK1_MAJOR SCSI_DISK1_MAJOR
+ #define XEN_SCSI_DISK2_MAJOR SCSI_DISK2_MAJOR
+ #define XEN_SCSI_DISK3_MAJOR SCSI_DISK3_MAJOR
+ #define XEN_SCSI_DISK4_MAJOR SCSI_DISK4_MAJOR
+ #define XEN_SCSI_DISK5_MAJOR SCSI_DISK5_MAJOR
+ #define XEN_SCSI_DISK6_MAJOR SCSI_DISK6_MAJOR
+ #define XEN_SCSI_DISK7_MAJOR SCSI_DISK7_MAJOR
+ #define XEN_SCSI_CDROM_MAJOR SCSI_CDROM_MAJOR
+
+ static dev_t vbd_map_devnum(blkif_pdev_t cookie)
+ {
+ int new_major;
+ int major = MAJOR_XEN(cookie);
+ int minor = MINOR_XEN(cookie);
+
+ switch (major) {
+ case XEN_IDE0_MAJOR: new_major = IDE0_MAJOR; break;
+ case XEN_IDE1_MAJOR: new_major = IDE1_MAJOR; break;
+ case XEN_IDE2_MAJOR: new_major = IDE2_MAJOR; break;
+ case XEN_IDE3_MAJOR: new_major = IDE3_MAJOR; break;
+ case XEN_IDE4_MAJOR: new_major = IDE4_MAJOR; break;
+ case XEN_IDE5_MAJOR: new_major = IDE5_MAJOR; break;
+ case XEN_IDE6_MAJOR: new_major = IDE6_MAJOR; break;
+ case XEN_IDE7_MAJOR: new_major = IDE7_MAJOR; break;
+ case XEN_IDE8_MAJOR: new_major = IDE8_MAJOR; break;
+ case XEN_IDE9_MAJOR: new_major = IDE9_MAJOR; break;
+ case XEN_SCSI_DISK0_MAJOR: new_major = SCSI_DISK0_MAJOR; break;
+ case XEN_SCSI_DISK1_MAJOR ... XEN_SCSI_DISK7_MAJOR:
+ new_major = SCSI_DISK1_MAJOR + major - XEN_SCSI_DISK1_MAJOR;
+ break;
+ case XEN_SCSI_CDROM_MAJOR: new_major = SCSI_CDROM_MAJOR; break;
+ default: new_major = 0; break;
+ }
+
+ return MKDEV(new_major, minor);
+ }
+ #endif
+
+ #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION_CODE(2,6,0) */
--- /dev/null
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
- if (str[0] == '=')
- str++;
-#endif
+ /******************************************************************************
+ * console.c
+ *
+ * Virtual console driver.
+ *
+ * Copyright (c) 2002-2004, K A Fraser.
+ *
+ * This file may be distributed separately from the Linux kernel, or
+ * incorporated into other software packages, subject to the following license:
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this source file (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy, modify,
+ * merge, publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+ #include <linux/config.h>
+ #include <linux/version.h>
+ #include <linux/module.h>
+ #include <linux/errno.h>
+ #include <linux/signal.h>
+ #include <linux/sched.h>
+ #include <linux/interrupt.h>
+ #include <linux/tty.h>
+ #include <linux/tty_flip.h>
+ #include <linux/serial.h>
+ #include <linux/major.h>
+ #include <linux/ptrace.h>
+ #include <linux/ioport.h>
+ #include <linux/mm.h>
+ #include <linux/slab.h>
+ #include <linux/init.h>
+ #include <linux/console.h>
+ #include <asm/io.h>
+ #include <asm/irq.h>
+ #include <asm/uaccess.h>
+ #include <asm-xen/xen-public/event_channel.h>
+ #include <asm-xen/hypervisor.h>
+ #include <asm-xen/evtchn.h>
+ #include <asm-xen/ctrl_if.h>
+
+ /*
+ * Modes:
+ * 'xencons=off' [XC_OFF]: Console is disabled.
+ * 'xencons=tty' [XC_TTY]: Console attached to '/dev/tty[0-9]+'.
+ * 'xencons=ttyS' [XC_SERIAL]: Console attached to '/dev/ttyS[0-9]+'.
+ * [XC_DEFAULT]: DOM0 -> XC_SERIAL ; all others -> XC_TTY.
+ *
+ * NB. In mode XC_TTY, we create dummy consoles for tty2-63. This suppresses
+ * warnings from standard distro startup scripts.
+ */
+ static enum { XC_OFF, XC_DEFAULT, XC_TTY, XC_SERIAL } xc_mode = XC_DEFAULT;
+
+ static int __init xencons_setup(char *str)
+ {
-__setup("xencons", xencons_setup);
+ if ( !strcmp(str, "tty") )
+ xc_mode = XC_TTY;
+ else if ( !strcmp(str, "ttyS") )
+ xc_mode = XC_SERIAL;
+ else if ( !strcmp(str, "off") )
+ xc_mode = XC_OFF;
+ return 1;
+ }
++__setup("xencons=", xencons_setup);
+
+ /* The kernel and user-land drivers share a common transmit buffer. */
+ #define WBUF_SIZE 4096
+ #define WBUF_MASK(_i) ((_i)&(WBUF_SIZE-1))
+ static char wbuf[WBUF_SIZE];
+ static unsigned int wc, wp; /* write_cons, write_prod */
+
+ /* This lock protects accesses to the common transmit buffer. */
+ static spinlock_t xencons_lock = SPIN_LOCK_UNLOCKED;
+
+ /* Common transmit-kick routine. */
+ static void __xencons_tx_flush(void);
+
+ /* This task is used to defer sending console data until there is space. */
+ static void xencons_tx_flush_task_routine(void *data);
+
+ static DECLARE_TQUEUE(xencons_tx_flush_task,
+ xencons_tx_flush_task_routine,
+ NULL);
+
+ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+ static struct tty_driver *xencons_driver;
+ #else
+ static struct tty_driver xencons_driver;
+ #endif
+
+
+ /******************** Kernel console driver ********************************/
+
+ static void kcons_write(
+ struct console *c, const char *s, unsigned int count)
+ {
+ int i;
+ unsigned long flags;
+
+ spin_lock_irqsave(&xencons_lock, flags);
+
+ for ( i = 0; i < count; i++ )
+ {
+ if ( (wp - wc) >= (WBUF_SIZE - 1) )
+ break;
+ if ( (wbuf[WBUF_MASK(wp++)] = s[i]) == '\n' )
+ wbuf[WBUF_MASK(wp++)] = '\r';
+ }
+
+ __xencons_tx_flush();
+
+ spin_unlock_irqrestore(&xencons_lock, flags);
+ }
+
+ static void kcons_write_dom0(
+ struct console *c, const char *s, unsigned int count)
+ {
+ int rc;
+
+ while ( count > 0 )
+ {
+ if ( (rc = HYPERVISOR_console_io(CONSOLEIO_write,
+ count, (char *)s)) > 0 )
+ {
+ count -= rc;
+ s += rc;
+ }
+ else
+ break;
+ }
+ }
+
+ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+ static struct tty_driver *kcons_device(struct console *c, int *index)
+ {
+ *index = c->index;
+ return xencons_driver;
+ }
+ #else
+ static kdev_t kcons_device(struct console *c)
+ {
+ return MKDEV(TTY_MAJOR, (xc_mode == XC_SERIAL) ? 64 : 1);
+ }
+ #endif
+
+ static struct console kcons_info = {
+ device: kcons_device,
+ flags: CON_PRINTBUFFER,
+ index: -1
+ };
+
+ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+ #define __RETCODE 0
+ static int __init xen_console_init(void)
+ #else
+ #define __RETCODE
+ void xen_console_init(void)
+ #endif
+ {
+ if ( xen_start_info.flags & SIF_INITDOMAIN )
+ {
+ if ( xc_mode == XC_DEFAULT )
+ xc_mode = XC_SERIAL;
+ kcons_info.write = kcons_write_dom0;
+ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+ if ( xc_mode == XC_SERIAL )
+ kcons_info.flags |= CON_ENABLED;
+ #endif
+ }
+ else
+ {
+ if ( xc_mode == XC_DEFAULT )
+ xc_mode = XC_TTY;
+ kcons_info.write = kcons_write;
+ }
+
+ if ( xc_mode == XC_OFF )
+ return __RETCODE;
+
+ if ( xc_mode == XC_SERIAL )
+ strcpy(kcons_info.name, "ttyS");
+ else
+ strcpy(kcons_info.name, "tty");
+
+ register_console(&kcons_info);
+ return __RETCODE;
+ }
+ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+ console_initcall(xen_console_init);
+ #endif
+
+ /*** Useful function for console debugging -- goes straight to Xen. ***/
+ asmlinkage int xprintk(const char *fmt, ...)
+ {
+ va_list args;
+ int printk_len;
+ static char printk_buf[1024];
+
+ /* Emit the output into the temporary buffer */
+ va_start(args, fmt);
+ printk_len = vsnprintf(printk_buf, sizeof(printk_buf), fmt, args);
+ va_end(args);
+
+ /* Send the processed output directly to Xen. */
+ kcons_write_dom0(NULL, printk_buf, printk_len);
+
+ return 0;
+ }
+
+ /*** Forcibly flush console data before dying. ***/
+ void xencons_force_flush(void)
+ {
+ ctrl_msg_t msg;
+ int sz;
+
+ /* Emergency console is synchronous, so there's nothing to flush. */
+ if ( xen_start_info.flags & SIF_INITDOMAIN )
+ return;
+
+ /*
+ * We use dangerous control-interface functions that require a quiescent
+ * system and no interrupts. Try to ensure this with a global cli().
+ */
+ cli();
+
+ /* Spin until console data is flushed through to the domain controller. */
+ while ( (wc != wp) && !ctrl_if_transmitter_empty() )
+ {
+ /* Interrupts are disabled -- we must manually reap responses. */
+ ctrl_if_discard_responses();
+
+ if ( (sz = wp - wc) == 0 )
+ continue;
+ if ( sz > sizeof(msg.msg) )
+ sz = sizeof(msg.msg);
+ if ( sz > (WBUF_SIZE - WBUF_MASK(wc)) )
+ sz = WBUF_SIZE - WBUF_MASK(wc);
+
+ msg.type = CMSG_CONSOLE;
+ msg.subtype = CMSG_CONSOLE_DATA;
+ msg.length = sz;
+ memcpy(msg.msg, &wbuf[WBUF_MASK(wc)], sz);
+
+ if ( ctrl_if_send_message_noblock(&msg, NULL, 0) == 0 )
+ wc += sz;
+ }
+ }
+
+
+ /******************** User-space console driver (/dev/console) ************/
+
+ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+ #define DRV(_d) (_d)
+ #define TTY_INDEX(_tty) ((_tty)->index)
+ #else
+ static int xencons_refcount;
+ static struct tty_struct *xencons_table[MAX_NR_CONSOLES];
+ #define DRV(_d) (&(_d))
+ #define TTY_INDEX(_tty) (MINOR((_tty)->device) - xencons_driver.minor_start)
+ #endif
+
+ static struct termios *xencons_termios[MAX_NR_CONSOLES];
+ static struct termios *xencons_termios_locked[MAX_NR_CONSOLES];
+ static struct tty_struct *xencons_tty;
+ static int xencons_priv_irq;
+ static char x_char;
+
+ /* Non-privileged receive callback. */
+ static void xencons_rx(ctrl_msg_t *msg, unsigned long id)
+ {
+ int i;
+ unsigned long flags;
+
+ spin_lock_irqsave(&xencons_lock, flags);
+ if ( xencons_tty != NULL )
+ {
+ for ( i = 0; i < msg->length; i++ )
+ tty_insert_flip_char(xencons_tty, msg->msg[i], 0);
+ tty_flip_buffer_push(xencons_tty);
+ }
+ spin_unlock_irqrestore(&xencons_lock, flags);
+
+ msg->length = 0;
+ ctrl_if_send_response(msg);
+ }
+
+ /* Privileged and non-privileged transmit worker. */
+ static void __xencons_tx_flush(void)
+ {
+ int sz, work_done = 0;
+ ctrl_msg_t msg;
+
+ if ( xen_start_info.flags & SIF_INITDOMAIN )
+ {
+ if ( x_char )
+ {
+ kcons_write_dom0(NULL, &x_char, 1);
+ x_char = 0;
+ work_done = 1;
+ }
+
+ while ( wc != wp )
+ {
+ sz = wp - wc;
+ if ( sz > (WBUF_SIZE - WBUF_MASK(wc)) )
+ sz = WBUF_SIZE - WBUF_MASK(wc);
+ kcons_write_dom0(NULL, &wbuf[WBUF_MASK(wc)], sz);
+ wc += sz;
+ work_done = 1;
+ }
+ }
+ else
+ {
+ while ( x_char )
+ {
+ msg.type = CMSG_CONSOLE;
+ msg.subtype = CMSG_CONSOLE_DATA;
+ msg.length = 1;
+ msg.msg[0] = x_char;
+
+ if ( ctrl_if_send_message_noblock(&msg, NULL, 0) == 0 )
+ x_char = 0;
+ else if ( ctrl_if_enqueue_space_callback(&xencons_tx_flush_task) )
+ break;
+
+ work_done = 1;
+ }
+
+ while ( wc != wp )
+ {
+ sz = wp - wc;
+ if ( sz > sizeof(msg.msg) )
+ sz = sizeof(msg.msg);
+ if ( sz > (WBUF_SIZE - WBUF_MASK(wc)) )
+ sz = WBUF_SIZE - WBUF_MASK(wc);
+
+ msg.type = CMSG_CONSOLE;
+ msg.subtype = CMSG_CONSOLE_DATA;
+ msg.length = sz;
+ memcpy(msg.msg, &wbuf[WBUF_MASK(wc)], sz);
+
+ if ( ctrl_if_send_message_noblock(&msg, NULL, 0) == 0 )
+ wc += sz;
+ else if ( ctrl_if_enqueue_space_callback(&xencons_tx_flush_task) )
+ break;
+
+ work_done = 1;
+ }
+ }
+
+ if ( work_done && (xencons_tty != NULL) )
+ {
+ wake_up_interruptible(&xencons_tty->write_wait);
+ if ( (xencons_tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
+ (xencons_tty->ldisc.write_wakeup != NULL) )
+ (xencons_tty->ldisc.write_wakeup)(xencons_tty);
+ }
+ }
+
+ /* Non-privileged transmit kicker. */
+ static void xencons_tx_flush_task_routine(void *data)
+ {
+ unsigned long flags;
+ spin_lock_irqsave(&xencons_lock, flags);
+ __xencons_tx_flush();
+ spin_unlock_irqrestore(&xencons_lock, flags);
+ }
+
+ /* Privileged receive callback and transmit kicker. */
+ static irqreturn_t xencons_priv_interrupt(int irq, void *dev_id,
+ struct pt_regs *regs)
+ {
+ static char rbuf[16];
+ int i, l;
+ unsigned long flags;
+
+ spin_lock_irqsave(&xencons_lock, flags);
+
+ if ( xencons_tty != NULL )
+ {
+ /* Receive work. */
+ while ( (l = HYPERVISOR_console_io(CONSOLEIO_read, 16, rbuf)) > 0 )
+ for ( i = 0; i < l; i++ )
+ tty_insert_flip_char(xencons_tty, rbuf[i], 0);
+ if ( xencons_tty->flip.count != 0 )
+ tty_flip_buffer_push(xencons_tty);
+ }
+
+ /* Transmit work. */
+ __xencons_tx_flush();
+
+ spin_unlock_irqrestore(&xencons_lock, flags);
+
+ return IRQ_HANDLED;
+ }
+
+ static int xencons_write_room(struct tty_struct *tty)
+ {
+ return WBUF_SIZE - (wp - wc);
+ }
+
+ static int xencons_chars_in_buffer(struct tty_struct *tty)
+ {
+ return wp - wc;
+ }
+
+ static void xencons_send_xchar(struct tty_struct *tty, char ch)
+ {
+ unsigned long flags;
+
+ if ( TTY_INDEX(tty) != 0 )
+ return;
+
+ spin_lock_irqsave(&xencons_lock, flags);
+ x_char = ch;
+ __xencons_tx_flush();
+ spin_unlock_irqrestore(&xencons_lock, flags);
+ }
+
+ static void xencons_throttle(struct tty_struct *tty)
+ {
+ if ( TTY_INDEX(tty) != 0 )
+ return;
+
+ if ( I_IXOFF(tty) )
+ xencons_send_xchar(tty, STOP_CHAR(tty));
+ }
+
+ static void xencons_unthrottle(struct tty_struct *tty)
+ {
+ if ( TTY_INDEX(tty) != 0 )
+ return;
+
+ if ( I_IXOFF(tty) )
+ {
+ if ( x_char != 0 )
+ x_char = 0;
+ else
+ xencons_send_xchar(tty, START_CHAR(tty));
+ }
+ }
+
+ static void xencons_flush_buffer(struct tty_struct *tty)
+ {
+ unsigned long flags;
+
+ if ( TTY_INDEX(tty) != 0 )
+ return;
+
+ spin_lock_irqsave(&xencons_lock, flags);
+ wc = wp = 0;
+ spin_unlock_irqrestore(&xencons_lock, flags);
+ }
+
+ static inline int __xencons_put_char(int ch)
+ {
+ char _ch = (char)ch;
+ if ( (wp - wc) == WBUF_SIZE )
+ return 0;
+ wbuf[WBUF_MASK(wp++)] = _ch;
+ return 1;
+ }
+
+ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+ static int xencons_write(struct tty_struct *tty, const unsigned char *buf,
+ int count)
+ {
+ int i;
+ unsigned long flags;
+
+ if ( TTY_INDEX(tty) != 0 )
+ return count;
+
+ spin_lock_irqsave(&xencons_lock, flags);
+
+ for ( i = 0; i < count; i++ )
+ if ( !__xencons_put_char(buf[i]) )
+ break;
+
+ if ( i != 0 )
+ __xencons_tx_flush();
+
+ spin_unlock_irqrestore(&xencons_lock, flags);
+
+ return i;
+ }
+ #else
+ static int xencons_write(struct tty_struct *tty, int from_user,
+ const u_char *buf, int count)
+ {
+ int i;
+ unsigned long flags;
+
+ if ( from_user && verify_area(VERIFY_READ, buf, count) )
+ return -EINVAL;
+
+ if ( TTY_INDEX(tty) != 0 )
+ return count;
+
+ spin_lock_irqsave(&xencons_lock, flags);
+
+ for ( i = 0; i < count; i++ )
+ {
+ char ch;
+ if ( from_user )
+ __get_user(ch, buf + i);
+ else
+ ch = buf[i];
+ if ( !__xencons_put_char(ch) )
+ break;
+ }
+
+ if ( i != 0 )
+ __xencons_tx_flush();
+
+ spin_unlock_irqrestore(&xencons_lock, flags);
+
+ return i;
+ }
+ #endif
+
+ static void xencons_put_char(struct tty_struct *tty, u_char ch)
+ {
+ unsigned long flags;
+
+ if ( TTY_INDEX(tty) != 0 )
+ return;
+
+ spin_lock_irqsave(&xencons_lock, flags);
+ (void)__xencons_put_char(ch);
+ spin_unlock_irqrestore(&xencons_lock, flags);
+ }
+
+ static void xencons_flush_chars(struct tty_struct *tty)
+ {
+ unsigned long flags;
+
+ if ( TTY_INDEX(tty) != 0 )
+ return;
+
+ spin_lock_irqsave(&xencons_lock, flags);
+ __xencons_tx_flush();
+ spin_unlock_irqrestore(&xencons_lock, flags);
+ }
+
+ static void xencons_wait_until_sent(struct tty_struct *tty, int timeout)
+ {
+ unsigned long orig_jiffies = jiffies;
+
+ if ( TTY_INDEX(tty) != 0 )
+ return;
+
+ while ( DRV(tty->driver)->chars_in_buffer(tty) )
+ {
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(1);
+ if ( signal_pending(current) )
+ break;
+ if ( (timeout != 0) && time_after(jiffies, orig_jiffies + timeout) )
+ break;
+ }
+
+ set_current_state(TASK_RUNNING);
+ }
+
+ static int xencons_open(struct tty_struct *tty, struct file *filp)
+ {
+ unsigned long flags;
+
+ if ( TTY_INDEX(tty) != 0 )
+ return 0;
+
+ spin_lock_irqsave(&xencons_lock, flags);
+ tty->driver_data = NULL;
+ if ( xencons_tty == NULL )
+ xencons_tty = tty;
+ __xencons_tx_flush();
+ spin_unlock_irqrestore(&xencons_lock, flags);
+
+ return 0;
+ }
+
+ static void xencons_close(struct tty_struct *tty, struct file *filp)
+ {
+ unsigned long flags;
+
+ if ( TTY_INDEX(tty) != 0 )
+ return;
+
+ if ( tty->count == 1 )
+ {
+ tty->closing = 1;
+ tty_wait_until_sent(tty, 0);
+ if ( DRV(tty->driver)->flush_buffer != NULL )
+ DRV(tty->driver)->flush_buffer(tty);
+ if ( tty->ldisc.flush_buffer != NULL )
+ tty->ldisc.flush_buffer(tty);
+ tty->closing = 0;
+ spin_lock_irqsave(&xencons_lock, flags);
+ xencons_tty = NULL;
+ spin_unlock_irqrestore(&xencons_lock, flags);
+ }
+ }
+
+ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+ static struct tty_operations xencons_ops = {
+ .open = xencons_open,
+ .close = xencons_close,
+ .write = xencons_write,
+ .write_room = xencons_write_room,
+ .put_char = xencons_put_char,
+ .flush_chars = xencons_flush_chars,
+ .chars_in_buffer = xencons_chars_in_buffer,
+ .send_xchar = xencons_send_xchar,
+ .flush_buffer = xencons_flush_buffer,
+ .throttle = xencons_throttle,
+ .unthrottle = xencons_unthrottle,
+ .wait_until_sent = xencons_wait_until_sent,
+ };
+
+ #ifdef CONFIG_XEN_PRIVILEGED_GUEST
+ static const char *xennullcon_startup(void)
+ {
+ return NULL;
+ }
+
+ static int xennullcon_dummy(void)
+ {
+ return 0;
+ }
+
+ #define DUMMY (void *)xennullcon_dummy
+
+ /*
+ * The console `switch' structure for the dummy console
+ *
+ * Most of the operations are dummies.
+ */
+
+ const struct consw xennull_con = {
+ .owner = THIS_MODULE,
+ .con_startup = xennullcon_startup,
+ .con_init = DUMMY,
+ .con_deinit = DUMMY,
+ .con_clear = DUMMY,
+ .con_putc = DUMMY,
+ .con_putcs = DUMMY,
+ .con_cursor = DUMMY,
+ .con_scroll = DUMMY,
+ .con_bmove = DUMMY,
+ .con_switch = DUMMY,
+ .con_blank = DUMMY,
+ .con_font_set = DUMMY,
+ .con_font_get = DUMMY,
+ .con_font_default = DUMMY,
+ .con_font_copy = DUMMY,
+ .con_set_palette = DUMMY,
+ .con_scrolldelta = DUMMY,
+ };
+ #endif
+ #endif
+
+ static int __init xencons_init(void)
+ {
+ int rc;
+
+ if ( xc_mode == XC_OFF )
+ return 0;
+
+ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+ xencons_driver = alloc_tty_driver((xc_mode == XC_SERIAL) ?
+ 1 : MAX_NR_CONSOLES);
+ if ( xencons_driver == NULL )
+ return -ENOMEM;
+ #else
+ memset(&xencons_driver, 0, sizeof(struct tty_driver));
+ xencons_driver.magic = TTY_DRIVER_MAGIC;
+ xencons_driver.refcount = &xencons_refcount;
+ xencons_driver.table = xencons_table;
+ xencons_driver.num = (xc_mode == XC_SERIAL) ? 1 : MAX_NR_CONSOLES;
+ #endif
+
+ DRV(xencons_driver)->major = TTY_MAJOR;
+ DRV(xencons_driver)->type = TTY_DRIVER_TYPE_SERIAL;
+ DRV(xencons_driver)->subtype = SERIAL_TYPE_NORMAL;
+ DRV(xencons_driver)->init_termios = tty_std_termios;
+ DRV(xencons_driver)->flags =
+ TTY_DRIVER_REAL_RAW | TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_NO_DEVFS;
+ DRV(xencons_driver)->termios = xencons_termios;
+ DRV(xencons_driver)->termios_locked = xencons_termios_locked;
+
+ if ( xc_mode == XC_SERIAL )
+ {
+ DRV(xencons_driver)->name = "ttyS";
+ DRV(xencons_driver)->minor_start = 64;
+ DRV(xencons_driver)->name_base = 0;
+ }
+ else
+ {
+ DRV(xencons_driver)->name = "tty";
+ DRV(xencons_driver)->minor_start = 1;
+ DRV(xencons_driver)->name_base = 1;
+ }
+
+ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+ tty_set_operations(xencons_driver, &xencons_ops);
+ #else
+ xencons_driver.open = xencons_open;
+ xencons_driver.close = xencons_close;
+ xencons_driver.write = xencons_write;
+ xencons_driver.write_room = xencons_write_room;
+ xencons_driver.put_char = xencons_put_char;
+ xencons_driver.flush_chars = xencons_flush_chars;
+ xencons_driver.chars_in_buffer = xencons_chars_in_buffer;
+ xencons_driver.send_xchar = xencons_send_xchar;
+ xencons_driver.flush_buffer = xencons_flush_buffer;
+ xencons_driver.throttle = xencons_throttle;
+ xencons_driver.unthrottle = xencons_unthrottle;
+ xencons_driver.wait_until_sent = xencons_wait_until_sent;
+ #endif
+
+ if ( (rc = tty_register_driver(DRV(xencons_driver))) != 0 )
+ {
+ printk("WARNING: Failed to register Xen virtual "
+ "console driver as '%s%d'\n",
+ DRV(xencons_driver)->name, DRV(xencons_driver)->name_base);
+ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+ put_tty_driver(xencons_driver);
+ xencons_driver = NULL;
+ #endif
+ return rc;
+ }
+
+ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+ tty_register_device(xencons_driver, 0, NULL);
+ #endif
+
+ if ( xen_start_info.flags & SIF_INITDOMAIN )
+ {
+ xencons_priv_irq = bind_virq_to_irq(VIRQ_CONSOLE);
+ (void)request_irq(xencons_priv_irq,
+ xencons_priv_interrupt, 0, "console", NULL);
+ }
+ else
+ {
+ (void)ctrl_if_register_receiver(CMSG_CONSOLE, xencons_rx, 0);
+ }
+
+ printk("Xen virtual console successfully installed as %s\n",
+ DRV(xencons_driver)->name);
+
+ return 0;
+ }
+
+ module_init(xencons_init);