diff options
author | cl349@arcadians.cl.cam.ac.uk <cl349@arcadians.cl.cam.ac.uk> | 2004-12-26 10:00:51 +0000 |
---|---|---|
committer | cl349@arcadians.cl.cam.ac.uk <cl349@arcadians.cl.cam.ac.uk> | 2004-12-26 10:00:51 +0000 |
commit | 7ada6cd67ff7153ce85d48d00c1c56af1dd2055c (patch) | |
tree | f0d0e41780b7ea059fb09bffadfe38591196577a | |
parent | 66ac336c5978db71606b1f1160ba16445ae81c91 (diff) | |
parent | 5dc6acb5fd57658377eb0e081ba7df8bfa35b558 (diff) | |
download | xen-7ada6cd67ff7153ce85d48d00c1c56af1dd2055c.tar.gz xen-7ada6cd67ff7153ce85d48d00c1c56af1dd2055c.tar.bz2 xen-7ada6cd67ff7153ce85d48d00c1c56af1dd2055c.zip |
bitkeeper revision 1.1159.170.64 (41ce8bd3sGsiOUiBHp1KyOcLPmYBgQ)
sync w/ head.
61 files changed, 1876 insertions, 321 deletions
@@ -318,6 +318,7 @@ 41090ec8Pj_bkgCBpg2W7WfmNkumEA tools/examples/xmexample1 40cf2937oKlROYOJTN8GWwWM5AmjBg tools/examples/xmexample2 3fbba6dbDfYvJSsw9500b4SZyUhxjQ tools/libxc/Makefile +41cc934abX-QLXJXW_clV_wRjM0zYg tools/libxc/plan9a.out.h 3fbba6dc1uU7U3IFeF6A-XEOYF2MkQ tools/libxc/rpm.spec 3fbba6dcrNxtygEcgJYAJJ1gCQqfsA tools/libxc/xc.h 40589968oCfoUlXd460CjVAkBE8IBA tools/libxc/xc_atropos.c @@ -332,6 +333,7 @@ 3fbba6db7li3FJiABYtCmuGxOJxEGw tools/libxc/xc_linux_save.c 3fbba6db7WnnJr0KFrIFrqNlSKvFYg tools/libxc/xc_misc.c 4051bce6CHAsYh8P5t2OHDtRWOP9og tools/libxc/xc_physdev.c +41cc934aO1m6NxEh_8eDr9bJIMoLFA tools/libxc/xc_plan9_build.c 3fbba6dctWRWlFJkYb6hdix2X4WMuw tools/libxc/xc_private.c 3fbba6dcbVrG2hPzEzwdeV_UC8kydQ tools/libxc/xc_private.h 40589968UQFnJeOMn8UIFLbXBuwXjw tools/libxc/xc_rrobin.c @@ -519,6 +521,7 @@ 411b2c1ehdEGO_CwG0tvn85Q-Tfh5g tools/python/xen/xm/migrate.py 40cf2937PSslwBliN1g7ofDy2H_RhA tools/python/xen/xm/opts.py 40cf2937Z8WCNOnO2FcWdubvEAF9QQ tools/python/xen/xm/shutdown.py +41b88ba6_C4---jeA895Efg9YFZgKA tools/python/xen/xm/sysrq.py 40fcefb2K1xqVVT4D-p7nL2GzS4scg tools/sv/Main.rpy 40ffbcb66Dj5F-1kCK9BcgSqCWkt1w tools/sv/Makefile 4120b0e5L_nW-u0MWRfIdXg4ng4OjA tools/sv/images/destroy.png @@ -690,7 +693,9 @@ 40f92331jfOlE7MfKwpdkEb1CEf23g xen/arch/x86/x86_32/seg_fixup.c 3ddb79bc4nTpGQOe6_-MbyZzkhlhFQ xen/arch/x86/x86_32/usercopy.c 3ddb79bcOMCu9-5mKpjIh5d0qqBDPg xen/arch/x86/x86_32/xen.lds +41bf1717Ty3hwN3E9swdu8QfnvGqww xen/arch/x86/x86_64/asm-offsets.c 40e96d3aLDI-nViMuYneD7VKYlZrVg xen/arch/x86/x86_64/entry.S +41bf1717XhPz_dNT5OKSjgmbFuWBuA xen/arch/x86/x86_64/mm.c 40e96d3ahBTZqbTViInnq0lM03vs7A xen/arch/x86/x86_64/usercopy.c 40e96d3akN3Hu_J5Bk-WXD8OGscrYQ xen/arch/x86/x86_64/xen.lds 3ddb79bdff-gj-jFGKjOejeHLqL8Lg xen/common/Makefile @@ -778,6 +783,7 @@ 40715b2dWe0tDhx9LkLXzTQkvD49RA xen/include/asm-x86/acpi.h 3ddb79c3l4IiQtf6MS2jIzcd-hJS8g xen/include/asm-x86/apic.h 3ddb79c3QJYWr8LLGdonLbWmNb9pQQ xen/include/asm-x86/apicdef.h +41bf17171g_hhz2k4B-fN9LQlODDjQ xen/include/asm-x86/asm_defns.h 3ddb79c3OiG9eTsi9Dy3F_OkuRAzKA xen/include/asm-x86/atomic.h 3ddb79c3rM-Ote0Xn6Ytg8Y6YqAG-A xen/include/asm-x86/bitops.h 3ddb79c3KhTI0F_Iw_hRL9QEyOVK-g xen/include/asm-x86/cache.h @@ -789,7 +795,6 @@ 3ddb79c3r9-31dIsewPV3P3i8HALsQ xen/include/asm-x86/delay.h 3ddb79c34BFiXjBJ_cCKB0aCsV1IDw xen/include/asm-x86/desc.h 40715b2dTokMLYGSuD58BnxOqyWVew xen/include/asm-x86/div64.h -40f2b4a2hC3HtChu-ArD8LyojxWMjg xen/include/asm-x86/domain.h 3e20b82fl1jmQiKdLy7fxMcutfpjWA xen/include/asm-x86/domain_page.h 3ddb79c3NU8Zy40OTrq3D-i30Y3t4A xen/include/asm-x86/fixmap.h 3e2d29944GI24gf7vOP_7x8EyuqxeA xen/include/asm-x86/flushtlb.h @@ -825,6 +830,7 @@ 3ddb79c3mbqEM7QQr3zVq7NiBNhouA xen/include/asm-x86/x86_32/regs.h 3e7f358aG11EvMI9VJ4_9hD4LUO7rQ xen/include/asm-x86/x86_32/string.h 3ddb79c3M2n1ROZH6xk3HbyN4CPDqg xen/include/asm-x86/x86_32/uaccess.h +41bf1717bML6GxpclTWJabiaO5W5vg xen/include/asm-x86/x86_64/asm_defns.h 404f1b9ceJeGVaPNIENm2FkK0AgEOQ xen/include/asm-x86/x86_64/current.h 404f1b9fl6AQ_a-T1TDK3fuwTPXmHw xen/include/asm-x86/x86_64/desc.h 404f1badfXZJZ2sU8sh9PS2EZvd19Q xen/include/asm-x86/x86_64/ldt.h @@ -852,6 +858,7 @@ 3eb165e0eawr3R-p2ZQtSdLWtLRN_A xen/include/xen/console.h 3ddb79c1V44RD26YqCUm-kqIupM37A xen/include/xen/ctype.h 3ddb79c05DdHQ0UxX_jKsXdR4QlMCA xen/include/xen/delay.h +40f2b4a2hC3HtChu-ArD8LyojxWMjg xen/include/xen/domain.h 3ddb79c2O729EttZTYu1c8LcsUO_GQ xen/include/xen/elf.h 3ddb79c0HIghfBF8zFUdmXhOU8i6hA xen/include/xen/errno.h 3ddb79c1W0lQca8gRV7sN6j3iY4Luw xen/include/xen/event.h diff --git a/linux-2.4.28-xen-sparse/arch/xen/kernel/time.c b/linux-2.4.28-xen-sparse/arch/xen/kernel/time.c index 0a04c6c3b6..9b3d40a08c 100644 --- a/linux-2.4.28-xen-sparse/arch/xen/kernel/time.c +++ b/linux-2.4.28-xen-sparse/arch/xen/kernel/time.c @@ -99,6 +99,10 @@ static u64 processed_system_time; /* System time (ns) at last processing. */ #define NS_PER_TICK (1000000000ULL/HZ) +#ifndef NSEC_PER_SEC +#define NSEC_PER_SEC (1000000000L) +#endif + #define HANDLE_USEC_UNDERFLOW(_tv) \ do { \ while ( (_tv).tv_usec < 0 ) \ @@ -115,6 +119,17 @@ static u64 processed_system_time; /* System time (ns) at last processing. */ (_tv).tv_sec++; \ } \ } while ( 0 ) +static inline void __normalize_time(time_t *sec, s64 *nsec) +{ + while (*nsec >= NSEC_PER_SEC) { + (*nsec) -= NSEC_PER_SEC; + (*sec)++; + } + while (*nsec < 0) { + (*nsec) += NSEC_PER_SEC; + (*sec)--; + } +} /* Dynamically-mapped IRQs. */ static int time_irq, debug_irq; @@ -256,6 +271,7 @@ void do_gettimeofday(struct timeval *tv) { unsigned long flags, lost; struct timeval _tv; + s64 nsec; again: read_lock_irqsave(&xtime_lock, flags); @@ -266,6 +282,10 @@ void do_gettimeofday(struct timeval *tv) _tv.tv_sec = xtime.tv_sec; _tv.tv_usec += xtime.tv_usec; + nsec = shadow_system_time - processed_system_time; + __normalize_time(&_tv.tv_sec, &nsec); + _tv.tv_usec += (long)nsec / 1000L; + if ( unlikely(!TIME_VALUES_UP_TO_DATE) ) { /* @@ -301,7 +321,8 @@ void do_gettimeofday(struct timeval *tv) void do_settimeofday(struct timeval *tv) { struct timeval newtv; - suseconds_t usec; + s64 nsec; + suseconds_t usec; if ( !INDEPENDENT_WALLCLOCK() ) return; @@ -315,6 +336,11 @@ void do_settimeofday(struct timeval *tv) */ again: usec = tv->tv_usec - __get_time_delta_usecs(); + + nsec = shadow_system_time - processed_system_time; + __normalize_time(&tv->tv_sec, &nsec); + usec -= (long)nsec / 1000L; + if ( unlikely(!TIME_VALUES_UP_TO_DATE) ) { __get_time_values_from_xen(); diff --git a/linux-2.4.28-xen-sparse/arch/xen/mm/init.c b/linux-2.4.28-xen-sparse/arch/xen/mm/init.c index dd622aebda..980983fd03 100644 --- a/linux-2.4.28-xen-sparse/arch/xen/mm/init.c +++ b/linux-2.4.28-xen-sparse/arch/xen/mm/init.c @@ -36,6 +36,10 @@ #include <asm/apic.h> #include <asm/tlb.h> +/* XEN: We *cannot* use mmx_clear_page() this early. Force dumb memset(). */ +#undef clear_page +#define clear_page(page) memset((void *)(page), 0, PAGE_SIZE) + mmu_gather_t mmu_gathers[NR_CPUS]; unsigned long highstart_pfn, highend_pfn; static unsigned long totalram_pages; diff --git a/linux-2.6.10-rc3-xen-sparse/arch/xen/configs/xen0_defconfig b/linux-2.6.10-rc3-xen-sparse/arch/xen/configs/xen0_defconfig index 98cbd2fdbf..d3ff092e5e 100644 --- a/linux-2.6.10-rc3-xen-sparse/arch/xen/configs/xen0_defconfig +++ b/linux-2.6.10-rc3-xen-sparse/arch/xen/configs/xen0_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit # Linux kernel version: 2.6.10-rc2-xen0 -# Wed Dec 1 09:22:49 2004 +# Thu Dec 23 14:01:43 2004 # CONFIG_XEN=y CONFIG_ARCH_XEN=y @@ -79,6 +79,11 @@ CONFIG_MMU=y CONFIG_UID16=y CONFIG_GENERIC_ISA_DMA=y CONFIG_GENERIC_IOMAP=y +# CONFIG_M386 is not set +# CONFIG_M486 is not set +# CONFIG_M586 is not set +# CONFIG_M586TSC is not set +# CONFIG_M586MMX is not set # CONFIG_M686 is not set # CONFIG_MPENTIUMII is not set # CONFIG_MPENTIUMIII is not set @@ -88,6 +93,9 @@ CONFIG_MPENTIUM4=y # CONFIG_MK7 is not set # CONFIG_MK8 is not set # CONFIG_MCRUSOE is not set +# CONFIG_MWINCHIPC6 is not set +# CONFIG_MWINCHIP2 is not set +# CONFIG_MWINCHIP3D is not set # CONFIG_MCYRIXIII is not set # CONFIG_MVIAC3_2 is not set # CONFIG_X86_GENERIC is not set diff --git a/linux-2.6.10-rc3-xen-sparse/arch/xen/configs/xenU_defconfig b/linux-2.6.10-rc3-xen-sparse/arch/xen/configs/xenU_defconfig index 2512c79cb1..0e7dc0a3b3 100644 --- a/linux-2.6.10-rc3-xen-sparse/arch/xen/configs/xenU_defconfig +++ b/linux-2.6.10-rc3-xen-sparse/arch/xen/configs/xenU_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit # Linux kernel version: 2.6.10-rc2-xenU -# Wed Dec 1 09:22:09 2004 +# Thu Dec 23 14:02:24 2004 # CONFIG_XEN=y CONFIG_ARCH_XEN=y @@ -78,6 +78,11 @@ CONFIG_MMU=y CONFIG_UID16=y CONFIG_GENERIC_ISA_DMA=y CONFIG_GENERIC_IOMAP=y +# CONFIG_M386 is not set +# CONFIG_M486 is not set +# CONFIG_M586 is not set +# CONFIG_M586TSC is not set +# CONFIG_M586MMX is not set # CONFIG_M686 is not set # CONFIG_MPENTIUMII is not set # CONFIG_MPENTIUMIII is not set @@ -87,6 +92,9 @@ CONFIG_MPENTIUM4=y # CONFIG_MK7 is not set # CONFIG_MK8 is not set # CONFIG_MCRUSOE is not set +# CONFIG_MWINCHIPC6 is not set +# CONFIG_MWINCHIP2 is not set +# CONFIG_MWINCHIP3D is not set # CONFIG_MCYRIXIII is not set # CONFIG_MVIAC3_2 is not set # CONFIG_X86_GENERIC is not set diff --git a/linux-2.6.10-rc3-xen-sparse/arch/xen/i386/Kconfig b/linux-2.6.10-rc3-xen-sparse/arch/xen/i386/Kconfig index d58f91fbd3..f34d271ff6 100644 --- a/linux-2.6.10-rc3-xen-sparse/arch/xen/i386/Kconfig +++ b/linux-2.6.10-rc3-xen-sparse/arch/xen/i386/Kconfig @@ -32,70 +32,70 @@ choice prompt "Processor family" default M686 -#config M386 -# bool "386" -# ---help--- -# This is the processor type of your CPU. This information is used for -# optimizing purposes. In order to compile a kernel that can run on -# all x86 CPU types (albeit not optimally fast), you can specify -# "386" here. -# -# The kernel will not necessarily run on earlier architectures than -# the one you have chosen, e.g. a Pentium optimized kernel will run on -# a PPro, but not necessarily on a i486. -# -# Here are the settings recommended for greatest speed: -# - "386" for the AMD/Cyrix/Intel 386DX/DXL/SL/SLC/SX, Cyrix/TI -# 486DLC/DLC2, UMC 486SX-S and NexGen Nx586. Only "386" kernels -# will run on a 386 class machine. -# - "486" for the AMD/Cyrix/IBM/Intel 486DX/DX2/DX4 or -# SL/SLC/SLC2/SLC3/SX/SX2 and UMC U5D or U5S. -# - "586" for generic Pentium CPUs lacking the TSC -# (time stamp counter) register. -# - "Pentium-Classic" for the Intel Pentium. -# - "Pentium-MMX" for the Intel Pentium MMX. -# - "Pentium-Pro" for the Intel Pentium Pro. -# - "Pentium-II" for the Intel Pentium II or pre-Coppermine Celeron. -# - "Pentium-III" for the Intel Pentium III or Coppermine Celeron. -# - "Pentium-4" for the Intel Pentium 4 or P4-based Celeron. -# - "K6" for the AMD K6, K6-II and K6-III (aka K6-3D). -# - "Athlon" for the AMD K7 family (Athlon/Duron/Thunderbird). -# - "Crusoe" for the Transmeta Crusoe series. +config M386 + bool "386" + ---help--- + This is the processor type of your CPU. This information is used for + optimizing purposes. In order to compile a kernel that can run on + all x86 CPU types (albeit not optimally fast), you can specify + "386" here. + + The kernel will not necessarily run on earlier architectures than + the one you have chosen, e.g. a Pentium optimized kernel will run on + a PPro, but not necessarily on a i486. + + Here are the settings recommended for greatest speed: + - "386" for the AMD/Cyrix/Intel 386DX/DXL/SL/SLC/SX, Cyrix/TI + 486DLC/DLC2, UMC 486SX-S and NexGen Nx586. Only "386" kernels + will run on a 386 class machine. + - "486" for the AMD/Cyrix/IBM/Intel 486DX/DX2/DX4 or + SL/SLC/SLC2/SLC3/SX/SX2 and UMC U5D or U5S. + - "586" for generic Pentium CPUs lacking the TSC + (time stamp counter) register. + - "Pentium-Classic" for the Intel Pentium. + - "Pentium-MMX" for the Intel Pentium MMX. + - "Pentium-Pro" for the Intel Pentium Pro. + - "Pentium-II" for the Intel Pentium II or pre-Coppermine Celeron. + - "Pentium-III" for the Intel Pentium III or Coppermine Celeron. + - "Pentium-4" for the Intel Pentium 4 or P4-based Celeron. + - "K6" for the AMD K6, K6-II and K6-III (aka K6-3D). + - "Athlon" for the AMD K7 family (Athlon/Duron/Thunderbird). + - "Crusoe" for the Transmeta Crusoe series. # - "Efficeon" for the Transmeta Efficeon series. -# - "Winchip-C6" for original IDT Winchip. -# - "Winchip-2" for IDT Winchip 2. -# - "Winchip-2A" for IDT Winchips with 3dNow! capabilities. -# - "CyrixIII/VIA C3" for VIA Cyrix III or VIA C3. -# - "VIA C3-2 for VIA C3-2 "Nehemiah" (model 9 and above). -# -# If you don't know what to do, choose "386". + - "Winchip-C6" for original IDT Winchip. + - "Winchip-2" for IDT Winchip 2. + - "Winchip-2A" for IDT Winchips with 3dNow! capabilities. + - "CyrixIII/VIA C3" for VIA Cyrix III or VIA C3. + - "VIA C3-2 for VIA C3-2 "Nehemiah" (model 9 and above). -#config M486 -# bool "486" -# help -# Select this for a 486 series processor, either Intel or one of the -# compatible processors from AMD, Cyrix, IBM, or Intel. Includes DX, -# DX2, and DX4 variants; also SL/SLC/SLC2/SLC3/SX/SX2 and UMC U5D or -# U5S. + If you don't know what to do, choose "386". -#config M586 -# bool "586/K5/5x86/6x86/6x86MX" -# help -# Select this for an 586 or 686 series processor such as the AMD K5, -# the Intel 5x86 or 6x86, or the Intel 6x86MX. This choice does not -# assume the RDTSC (Read Time Stamp Counter) instruction. +config M486 + bool "486" + help + Select this for a 486 series processor, either Intel or one of the + compatible processors from AMD, Cyrix, IBM, or Intel. Includes DX, + DX2, and DX4 variants; also SL/SLC/SLC2/SLC3/SX/SX2 and UMC U5D or + U5S. -#config M586TSC -# bool "Pentium-Classic" -# help -# Select this for a Pentium Classic processor with the RDTSC (Read -# Time Stamp Counter) instruction for benchmarking. +config M586 + bool "586/K5/5x86/6x86/6x86MX" + help + Select this for an 586 or 686 series processor such as the AMD K5, + the Intel 5x86 or 6x86, or the Intel 6x86MX. This choice does not + assume the RDTSC (Read Time Stamp Counter) instruction. -#config M586MMX -# bool "Pentium-MMX" -# help -# Select this for a Pentium with the MMX graphics/multimedia -# extended instructions. +config M586TSC + bool "Pentium-Classic" + help + Select this for a Pentium Classic processor with the RDTSC (Read + Time Stamp Counter) instruction for benchmarking. + +config M586MMX + bool "Pentium-MMX" + help + Select this for a Pentium with the MMX graphics/multimedia + extended instructions. config M686 bool "Pentium-Pro" @@ -164,33 +164,33 @@ config MCRUSOE like a 586 with TSC, and sets some GCC optimization flags (like a Pentium Pro with no alignment requirements). -#config MEFFICEON -# bool "Efficeon" -# help -# Select this for a Transmeta Efficeon processor. +config MEFFICEON + bool "Efficeon" + help + Select this for a Transmeta Efficeon processor. -#config MWINCHIPC6 -# bool "Winchip-C6" -# help -# Select this for an IDT Winchip C6 chip. Linux and GCC -# treat this chip as a 586TSC with some extended instructions -# and alignment requirements. +config MWINCHIPC6 + bool "Winchip-C6" + help + Select this for an IDT Winchip C6 chip. Linux and GCC + treat this chip as a 586TSC with some extended instructions + and alignment requirements. -#config MWINCHIP2 -# bool "Winchip-2" -# help -# Select this for an IDT Winchip-2. Linux and GCC -# treat this chip as a 586TSC with some extended instructions -# and alignment requirements. +config MWINCHIP2 + bool "Winchip-2" + help + Select this for an IDT Winchip-2. Linux and GCC + treat this chip as a 586TSC with some extended instructions + and alignment requirements. -#config MWINCHIP3D -# bool "Winchip-2A/Winchip-3" -# help -# Select this for an IDT Winchip-2A or 3. Linux and GCC -# treat this chip as a 586TSC with some extended instructions -# and alignment reqirements. Also enable out of order memory -# stores for this CPU, which can increase performance of some -# operations. +config MWINCHIP3D + bool "Winchip-2A/Winchip-3" + help + Select this for an IDT Winchip-2A or 3. Linux and GCC + treat this chip as a 586TSC with some extended instructions + and alignment reqirements. Also enable out of order memory + stores for this CPU, which can increase performance of some + operations. config MCYRIXIII bool "CyrixIII/VIA-C3" diff --git a/linux-2.6.10-rc3-xen-sparse/arch/xen/i386/kernel/traps.c b/linux-2.6.10-rc3-xen-sparse/arch/xen/i386/kernel/traps.c index c837f935b4..1936d96c37 100644 --- a/linux-2.6.10-rc3-xen-sparse/arch/xen/i386/kernel/traps.c +++ b/linux-2.6.10-rc3-xen-sparse/arch/xen/i386/kernel/traps.c @@ -979,7 +979,6 @@ void __init trap_init(void) * default LDT is a single-entry callgate to lcall7 for iBCS * and a callgate to lcall27 for Solaris/x86 binaries */ - clear_page(&default_ldt[0]); make_lowmem_page_readonly(&default_ldt[0]); xen_flush_page_update_queue(); diff --git a/linux-2.6.10-rc3-xen-sparse/arch/xen/kernel/reboot.c b/linux-2.6.10-rc3-xen-sparse/arch/xen/kernel/reboot.c index 1f7303efd2..78c46675f5 100644 --- a/linux-2.6.10-rc3-xen-sparse/arch/xen/kernel/reboot.c +++ b/linux-2.6.10-rc3-xen-sparse/arch/xen/kernel/reboot.c @@ -8,6 +8,7 @@ static int errno; #include <linux/unistd.h> #include <linux/module.h> #include <linux/reboot.h> +#include <linux/sysrq.h> #include <asm/irq.h> #include <asm/mmu_context.h> #include <asm-xen/ctrl_if.h> @@ -49,10 +50,9 @@ EXPORT_SYMBOL(machine_power_off); * Stop/pickle callback handling. */ -//#include <asm/suspend.h> - /* Ignore multiple shutdown requests. */ static int shutting_down = -1; +static int pending_sysrq = -1; static void __do_suspend(void) { @@ -214,9 +214,18 @@ static void __shutdown_handler(void *unused) } } +static void __sysrq_handler(void *unused) +{ +#ifdef CONFIG_MAGIC_SYSRQ + handle_sysrq(pending_sysrq, NULL, NULL); +#endif + pending_sysrq = -1; +} + static void shutdown_handler(ctrl_msg_t *msg, unsigned long id) { static DECLARE_WORK(shutdown_work, __shutdown_handler, NULL); + static DECLARE_WORK(sysrq_work, __sysrq_handler, NULL); if ( (shutting_down == -1) && ((msg->subtype == CMSG_SHUTDOWN_POWEROFF) || @@ -226,6 +235,12 @@ static void shutdown_handler(ctrl_msg_t *msg, unsigned long id) shutting_down = msg->subtype; schedule_work(&shutdown_work); } + else if ( (pending_sysrq == -1) && + (msg->subtype == CMSG_SHUTDOWN_SYSRQ) ) + { + pending_sysrq = msg->msg[0]; + schedule_work(&sysrq_work); + } else { printk("Ignore spurious shutdown request\n"); diff --git a/linux-2.6.10-rc3-xen-sparse/drivers/xen/netback/interface.c b/linux-2.6.10-rc3-xen-sparse/drivers/xen/netback/interface.c index baa50ace22..8de03f644b 100644 --- a/linux-2.6.10-rc3-xen-sparse/drivers/xen/netback/interface.c +++ b/linux-2.6.10-rc3-xen-sparse/drivers/xen/netback/interface.c @@ -124,13 +124,17 @@ void netif_create(netif_be_create_t *create) dev->hard_start_xmit = netif_be_start_xmit; dev->get_stats = netif_be_get_stats; - memcpy(dev->dev_addr, create->mac, ETH_ALEN); /* Disable queuing. */ dev->tx_queue_len = 0; - /* Force a different MAC from remote end. */ - dev->dev_addr[2] ^= 1; + /* + * Initialise a dummy MAC address. We choose the numerically largest + * non-broadcast address to prevent the address getting stolen by an + * Ethernet bridge for STP purposes. (FE:FF:FF:FF:FF:FF) + */ + memset(dev->dev_addr, 0xFF, ETH_ALEN); + dev->dev_addr[0] &= ~0x01; if ( (err = register_netdev(dev)) != 0 ) { diff --git a/tools/libxc/Makefile b/tools/libxc/Makefile index 9065bb1bd6..6ee078644c 100644 --- a/tools/libxc/Makefile +++ b/tools/libxc/Makefile @@ -18,6 +18,7 @@ SRCS += xc_domain.c SRCS += xc_evtchn.c SRCS += xc_io.c SRCS += xc_linux_build.c +SRCS += xc_plan9_build.c SRCS += xc_linux_restore.c SRCS += xc_linux_save.c SRCS += xc_misc.c diff --git a/tools/libxc/plan9a.out.h b/tools/libxc/plan9a.out.h new file mode 100755 index 0000000000..d53f636517 --- /dev/null +++ b/tools/libxc/plan9a.out.h @@ -0,0 +1,28 @@ + +typedef struct Exec +{ + long magic; /* magic number */ + long text; /* size of text segment */ + long data; /* size of initialized data */ + long bss; /* size of uninitialized data */ + long syms; /* size of symbol table */ + long entry; /* entry point */ + long spsz; /* size of pc/sp offset table */ + long pcsz; /* size of pc/line number table */ +} Exec; + +#define _MAGIC(b) ((((4*b)+0)*b)+7) +#define A_MAGIC _MAGIC(8) /* 68020 */ +#define I_MAGIC _MAGIC(11) /* intel 386 */ +#define J_MAGIC _MAGIC(12) /* intel 960 */ +#define K_MAGIC _MAGIC(13) /* sparc */ +#define V_MAGIC _MAGIC(16) /* mips 3000 */ +#define X_MAGIC _MAGIC(17) /* att dsp 3210 */ +#define M_MAGIC _MAGIC(18) /* mips 4000 */ +#define D_MAGIC _MAGIC(19) /* amd 29000 */ +#define E_MAGIC _MAGIC(20) /* arm 7-something */ +#define Q_MAGIC _MAGIC(21) /* powerpc */ +#define N_MAGIC _MAGIC(22) /* mips 4000 LE */ +#define L_MAGIC _MAGIC(23) /* dec alpha */ +#define P_MAGIC _MAGIC(24) /* mips 3000 LE */ + diff --git a/tools/libxc/xc.h b/tools/libxc/xc.h index 18665e9178..72dfd3c4e6 100644 --- a/tools/libxc/xc.h +++ b/tools/libxc/xc.h @@ -9,14 +9,15 @@ #ifndef __XC_H__ #define __XC_H__ -typedef unsigned char u8; -typedef unsigned short u16; -typedef unsigned long u32; -typedef unsigned long long u64; -typedef signed char s8; -typedef signed short s16; -typedef signed long s32; -typedef signed long long s64; +#include <stdint.h> +typedef uint8_t u8; +typedef uint16_t u16; +typedef uint32_t u32; +typedef uint64_t u64; +typedef int8_t s8; +typedef int16_t s16; +typedef int32_t s32; +typedef int64_t s64; #include <xen/xen.h> #include <xen/dom0_ops.h> @@ -96,6 +97,14 @@ int xc_linux_build(int xc_handle, unsigned int control_evtchn, unsigned long flags); +int +xc_plan9_build (int xc_handle, + u32 domid, + const char *image_name, + const char *cmdline, + unsigned int control_evtchn, + unsigned long flags); + int xc_bvtsched_global_set(int xc_handle, unsigned long ctx_allow); diff --git a/tools/libxc/xc_linux_save.c b/tools/libxc/xc_linux_save.c index 9ff85a241b..6d877c84f0 100644 --- a/tools/libxc/xc_linux_save.c +++ b/tools/libxc/xc_linux_save.c @@ -6,6 +6,7 @@ * Copyright (c) 2003, K A Fraser. */ +#include <inttypes.h> #include <sys/time.h> #include "xc_private.h" #include <xen/linux/suspend.h> @@ -245,7 +246,7 @@ static int print_stats( int xc_handle, u32 domid, if ( print ) printf("delta %lldms, dom0 %d%%, target %d%%, sent %dMb/s, " - "dirtied %dMb/s %ld pages\n", + "dirtied %dMb/s %" PRId32 " pages\n", wall_delta, (int)((d0_cpu_delta*100)/wall_delta), (int)((d1_cpu_delta*100)/wall_delta), @@ -307,8 +308,8 @@ static int analysis_phase( int xc_handle, u32 domid, DOM0_SHADOW_CONTROL_OP_PEEK, NULL, 0, &stats); - printf("now= %lld faults= %ld dirty= %ld dirty_net= %ld " - "dirty_block= %ld\n", + printf("now= %lld faults= %" PRId32 " dirty= %" PRId32 + " dirty_net= %" PRId32 " dirty_block= %" PRId32"\n", ((now-start)+500)/1000, stats.fault_count, stats.dirty_count, stats.dirty_net_count, stats.dirty_block_count); diff --git a/tools/libxc/xc_plan9_build.c b/tools/libxc/xc_plan9_build.c new file mode 100755 index 0000000000..33c9a54914 --- /dev/null +++ b/tools/libxc/xc_plan9_build.c @@ -0,0 +1,744 @@ +/****************************************************************************** + * xc_plan9_build.c + * derived from xc_linux_build.c + */ + +#include "xc_private.h" + +#include <zlib.h> + +#define DEBUG 1 +#ifdef DEBUG +#define DPRINTF(x) printf x; fflush(stdout); +#else +#define DPRINTF(x) +#endif + +#include "plan9a.out.h" + +/* really TOS which means stack starts at 0x2000, and uses page 1*/ +#define STACKPAGE 2 +struct Exec header, origheader; + +typedef struct page { + char data[PAGE_SIZE]; +} PAGE; + + +int +memcpy_toguest(int xc_handle, u32 dom, void *v, int size, + unsigned long *page_array, unsigned int to_page) +{ + int ret; + unsigned char *cp = v; + unsigned int whichpage; + unsigned char *vaddr; + +// DPRINTF(("memcpy_to_guest: to_page 0x%x, count %d\n", to_page, size)); + for (ret = 0, whichpage = to_page; size > 0; + whichpage++, size -= PAGE_SIZE, cp += PAGE_SIZE) { + + // DPRINTF (("map_pfn_writeable(%p, 0x%lx)\n", pm_handle, +// page_array[whichpage])); + vaddr = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE, + PROT_READ | PROT_WRITE, + page_array[whichpage]); + // DPRINTF (("vaddr is %p\n", vaddr)); + if (vaddr == NULL) { + ret = -1; + ERROR("Couldn't map guest memory"); + goto out; + } + // DPRINTF (("copy %p to %p, count 0x%x\n", cp, vaddr, 4096)); + memcpy(vaddr, cp, 4096); + munmap(vaddr, PAGE_SIZE); + // DPRINTF (("Did %ud'th pages\n", whichpage)); + } + out: + return ret; +} + +/* this is a function which can go away. It dumps a hunk of + * guest pages to a file (/tmp/dumpit); handy for debugging + * your image builder. + * Xen guys, nuke this if you wish. + */ +void +dumpit(int xc_handle, u32 dom, + int start_page, int tot, unsigned long *page_array) +{ + int i, ofd; + unsigned char *vaddr; + + ofd = open("/tmp/dumpit", O_RDWR); + for (i = start_page; i < tot; i++) { + vaddr = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE, + PROT_READ | PROT_WRITE, + page_array[i]); + if (!vaddr) { + fprintf(stderr, "Page %d\n", i); + perror("shit"); + read(0, &i, 1); + return; + } + write(ofd, vaddr, 4096); + munmap(vaddr, PAGE_SIZE); + } +} +int +blah(char *b) +{ + fprintf(stderr, "Error in xc_plan9_build!\n"); + perror(b); + return errno; +} + +/* swap bytes. For plan 9 headers */ +void +swabby(unsigned long *s, char *name) +{ + unsigned long it; + it = ((*s & 0xff000000) >> 24) | ((*s & 0xff0000) >> 8) | + ((*s & 0xff00) << 8) | ((*s & 0xff) << 24); + DPRINTF(("Item %s is 0x%lx\n", name, it)); + *s = it; +} + +void +plan9header(Exec * header) +{ + /* header is big-endian */ + swabby(&header->magic, "magic"); + swabby(&header->text, "text"); + swabby(&header->data, "data"); + swabby(&header->bss, "bss"); + swabby(&header->syms, "syms"); + swabby(&header->entry, "entry"); + swabby(&header->spsz, "spsz"); + swabby(&header->pcsz, "pcsz"); + +} + +static int + loadp9image(gzFile kernel_gfd, int xc_handle, u32 dom, + unsigned long *page_array, + unsigned long tot_pages, unsigned long *virt_load_addr, + unsigned long *ksize, unsigned long *symtab_addr, + unsigned long *symtab_len, + unsigned long *first_data_page, unsigned long *pdb_page); + +#define P9ROUND (P9SIZE / 8) + +#define L1_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED) +#define L2_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER) + +static long +get_tot_pages(int xc_handle, u32 domid) +{ + dom0_op_t op; + op.cmd = DOM0_GETDOMAININFO; + op.u.getdomaininfo.domain = (domid_t) domid; + op.u.getdomaininfo.ctxt = NULL; + return (do_dom0_op(xc_handle, &op) < 0) ? + -1 : op.u.getdomaininfo.tot_pages; +} + +static int +get_pfn_list(int xc_handle, + u32 domid, unsigned long *pfn_buf, unsigned long max_pfns) +{ + dom0_op_t op; + int ret; + op.cmd = DOM0_GETMEMLIST; + op.u.getmemlist.domain = (domid_t) domid; + op.u.getmemlist.max_pfns = max_pfns; + op.u.getmemlist.buffer = pfn_buf; + + if (mlock(pfn_buf, max_pfns * sizeof (unsigned long)) != 0) + return -1; + + ret = do_dom0_op(xc_handle, &op); + + (void) munlock(pfn_buf, max_pfns * sizeof (unsigned long)); + +#if 0 +#ifdef DEBUG + DPRINTF(("Ret for get_pfn_list is %d\n", ret)); + if (ret >= 0) { + int i, j; + for (i = 0; i < op.u.getmemlist.num_pfns; i += 16) { + fprintf(stderr, "0x%x: ", i); + for (j = 0; j < 16; j++) + fprintf(stderr, "0x%lx ", pfn_buf[i + j]); + fprintf(stderr, "\n"); + } + } +#endif +#endif + return (ret < 0) ? -1 : op.u.getmemlist.num_pfns; +} + +static int +setup_guestos(int xc_handle, + u32 dom, + gzFile kernel_gfd, + unsigned long tot_pages, + unsigned long *virt_startinfo_addr, + unsigned long *virt_load_addr, + full_execution_context_t * ctxt, + const char *cmdline, + unsigned long shared_info_frame, + unsigned int control_evtchn, + int flags) +{ + l1_pgentry_t *vl1e = NULL; + l2_pgentry_t *vl2tab = NULL, *vl2e = NULL; + unsigned long *cpage_array = NULL; + unsigned long *pte_array = NULL; + unsigned long l2tab; + unsigned long l1tab; + unsigned long count; + unsigned long symtab_addr = 0, symtab_len = 0; + start_info_t *start_info; + shared_info_t *shared_info; + unsigned long ksize; + mmu_t *mmu = NULL; + int i; + unsigned long first_page_after_kernel, + first_data_page, + page_array_page; + unsigned long cpu0pdb, cpu0pte, cpu0ptelast; + unsigned long /*last_pfn, */ tot_pte_pages; + + DPRINTF(("tot pages is %ld\n", tot_pages)); + if ((cpage_array = malloc(tot_pages * sizeof (unsigned long))) == NULL) { + PERROR("Could not allocate cpage array"); + goto error_out; + } + + if (get_pfn_list(xc_handle, dom, cpage_array, tot_pages) != tot_pages) { + PERROR("Could not get the page frame list"); + goto error_out; + } + + for (i = 0; i < 64; i++) + DPRINTF(("First %d page is 0x%lx\n", i, cpage_array[i])); + + tot_pte_pages = tot_pages >> 10; + DPRINTF(("Page range is 0 to 0x%lx, which requires 0x%lx pte pages\n", + tot_pte_pages, tot_pte_pages)); + + if (loadp9image(kernel_gfd, xc_handle, dom, cpage_array, tot_pages, + virt_load_addr, &ksize, &symtab_addr, &symtab_len, + &first_data_page, &first_page_after_kernel)) + goto error_out; + DPRINTF(("First data page is 0x%lx\n", first_data_page)); + DPRINTF(("First page after kernel is 0x%lx\n", + first_page_after_kernel)); + + /* + NEED TO INCREMENT first page after kernel by: + + 1 (pdb) + + tot_pte_pages (pte) + + tot_pte_pages (page_array) + */ + /* SO, have to copy the first kernel pages pfns right into the + * page_array, then do identity maps for the rest. + */ + DPRINTF(("mapped kernel pages\n")); + + /* now loop over all ptes and store into the page_array, so as + * to get the identity map. + */ + if ((pte_array = + malloc(tot_pte_pages * 1024 * sizeof (unsigned long))) == NULL) { + PERROR("Could not allocate pte array"); + goto error_out; + } + + /* plan 9 on startup expects a "l2" (xen parlance) at 0x2000, + * this "l2" should have one PTE pointer for a va of 0x80000000. + * and an l1 (PTEs to you) at 0x3000. (physical). + * the PTEs should map the first 4M of memory. + */ + /* get a physical address for the L2. This means take the PFN and + * shift left. + */ + /* this terminology is plan 9 terminology. + * pdb is essentially the Xen L2. 'Page Directory Block'? + * I need to ask JMK. + * cpupte is the pte array. + * Plan 9 counts on these being set up for cpu0. + * SO: cpu0pdb (Xen L2) + * and cpupte (Xen L1) + */ + /* cpu0pdb is right after kernel */ + cpu0pdb = first_page_after_kernel; + /* cpu0pte comes right after cpu0pdb */ + cpu0pte = cpu0pdb + 1; + /* number of the past cpu0pte page */ + cpu0ptelast = cpu0pte + tot_pte_pages - 1; + /* first page of the page array (mfn) */ + page_array_page = cpu0ptelast + 1; + + DPRINTF(("cpu0pdb 0x%lx, cpu0pte 0x%lx cpu0ptelast 0x%lx\n", cpu0pdb, + cpu0pte, cpu0ptelast)); + l2tab = cpage_array[cpu0pdb] << PAGE_SHIFT; + DPRINTF(("l2tab 0x%lx\n", l2tab)); + ctxt->pt_base = l2tab; + + /* get a physical address for the L1. This means take the PFN and + * shift left. + */ + l1tab = cpage_array[cpu0pte] << PAGE_SHIFT; + DPRINTF(("l1tab 0x%lx\n", l1tab)); + if ((mmu = init_mmu_updates(xc_handle, dom)) == NULL) + goto error_out; + DPRINTF(("now map in l2tab\n")); + + /* Initialise the page tables. */ + /* mmap in the l2tab */ + if ((vl2tab = xc_map_foreign_range(xc_handle, dom, + PAGE_SIZE, PROT_READ | PROT_WRITE, + l2tab >> PAGE_SHIFT)) == NULL) + goto error_out; + DPRINTF(("vl2tab 0x%p\n", vl2tab)); + /* now we have the cpu0pdb for the kernel, starting at 0x2000, + * so we can plug in the physical pointer to the 0x3000 pte + */ + /* zero it */ + memset(vl2tab, 0, PAGE_SIZE); + /* get a pointer in the l2tab for the virt_load_addr */ + DPRINTF(("&vl2tab[l2_table_offset(*virt_load_addr)] is 0x%p[0x%lx]\n", + &vl2tab[l2_table_offset(*virt_load_addr)], + l2_table_offset(*virt_load_addr))); + + vl2e = &vl2tab[l2_table_offset(*virt_load_addr)]; + + /* OK, for all the available PTE, set the PTE pointer up */ + DPRINTF(("For i = %ld to %ld ...\n", cpu0pte, cpu0ptelast)); + for (i = cpu0pte; i <= cpu0ptelast; i++) { + DPRINTF(("Index %d Set %p to 0x%lx\n", i, vl2e, + (cpage_array[i] << PAGE_SHIFT) | L2_PROT)); + *vl2e++ = (cpage_array[i] << PAGE_SHIFT) | L2_PROT; + } + + /* unmap it ... */ + munmap(vl2tab, PAGE_SIZE); + + /* for the pages from virt_load_pointer to the end of this + * set of PTEs, map in the PFN for that VA + */ + for (vl1e = (l1_pgentry_t *) pte_array, count = 0; + count < tot_pte_pages * 1024; count++, vl1e++) { + + *vl1e = cpage_array[count]; + if (!cpage_array[count]) + continue; + /* set in the PFN for this entry */ + *vl1e = (cpage_array[count] << PAGE_SHIFT) | L1_PROT; +/* + DPRINTF (("vl1e # %d 0x%lx gets 0x%lx\n", + count, vl1e, *vl1e)); +*/ + if ((count >= cpu0pdb) && (count <= cpu0ptelast)) { + //DPRINTF((" Fix up page %d as it is in pte ville: ", count)); + *vl1e &= ~_PAGE_RW; + DPRINTF(("0x%lx\n", *vl1e)); + } + if ((count >= (0x100000 >> 12)) + && (count < (first_data_page >> 12))) { + //DPRINTF((" Fix up page %d as it is in text ", count)); + *vl1e &= ~_PAGE_RW; + //DPRINTF (("0x%lx\n", *vl1e)); + } + } + /* special thing. Pre-map the shared info page */ + vl1e = &pte_array[2]; + *vl1e = (shared_info_frame << PAGE_SHIFT) | L1_PROT; + DPRINTF(("v1l1 %p, has value 0x%lx\n", vl1e, *(unsigned long *) vl1e)); + /* another special thing. VA 80005000 has to point to 80006000 */ + /* this is a Plan 9 thing -- the 'mach' pointer */ + /* 80005000 is the mach pointer per-cpu, and the actual + * mach pointers are 80006000, 80007000 etc. + */ + vl1e = &pte_array[5]; + *vl1e = (cpage_array[6] << PAGE_SHIFT) | L1_PROT; + + /* OK, it's all set up, copy it in */ + memcpy_toguest(xc_handle, dom, pte_array, + (tot_pte_pages * 1024 * sizeof (unsigned long) /**/), + cpage_array, cpu0pte); + + /* We really need to have the vl1tab unmapped or the add_mmu_update + * below will fail bigtime. + */ + /* Xen guys: remember my errors on domain exit? Something I'm doing + * wrong in here? We never did find out ... + */ + /* get rid of the entries we can not use ... */ + memcpy_toguest(xc_handle, dom, cpage_array, + (tot_pte_pages * 1024 * sizeof (unsigned long) /**/), + cpage_array, page_array_page); + /* last chance to dump all of memory */ + // dumpit(xc_handle, dom, 0 /*0x100000>>12*/, tot_pages, cpage_array) ; + /* + * Pin down l2tab addr as page dir page - causes hypervisor to provide + * correct protection for the page + */ + if (add_mmu_update(xc_handle, mmu, + l2tab | MMU_EXTENDED_COMMAND, MMUEXT_PIN_L2_TABLE)) + goto error_out; + + for (count = 0; count < tot_pages; count++) { +/* + DPRINTF (("add_mmu_update(0x%x, 0x%x, 0x%x, %d)\n", xc_handle, mmu, + (cpage_array[count] + << PAGE_SHIFT) | + MMU_MACHPHYS_UPDATE, + count)); +*/ + if (add_mmu_update(xc_handle, mmu, + (cpage_array[count] << PAGE_SHIFT) | + MMU_MACHPHYS_UPDATE, count)) + goto error_out; + //DPRINTF(("Do the next one\n")); + } +/* + */ + + //dumpit(pm_handle, 3, 4, page_array); + /* put the virt_startinfo_addr at KZERO */ + /* just hard-code for now */ + *virt_startinfo_addr = 0x80000000; + + DPRINTF(("virt_startinfo_addr = 0x%lx\n", *virt_startinfo_addr)); + start_info = xc_map_foreign_range(xc_handle, dom, + PAGE_SIZE, PROT_READ | PROT_WRITE, + cpage_array[0]); + DPRINTF(("startinfo = 0x%p\n", start_info)); + DPRINTF(("shared_info_frame is %lx\n", shared_info_frame)); + memset(start_info, 0, sizeof (*start_info)); + start_info->pt_base = 0x80000000 | cpu0pdb << PAGE_SHIFT; + start_info->mfn_list = 0x80000000 | (page_array_page) << PAGE_SHIFT; + DPRINTF(("mfn_list 0x%lx\n", start_info->mfn_list)); + start_info->mod_start = 0; + start_info->mod_len = 0; + start_info->nr_pages = tot_pte_pages * 1024; + start_info->nr_pt_frames = tot_pte_pages + 1; + start_info->shared_info = shared_info_frame; + start_info->flags = 0; + DPRINTF((" control event channel is %d\n", control_evtchn)); + start_info->domain_controller_evtchn = control_evtchn; + strncpy(start_info->cmd_line, cmdline, MAX_CMDLINE); + start_info->cmd_line[MAX_CMDLINE - 1] = '\0'; + munmap(start_info, PAGE_SIZE); + + DPRINTF(("done setting up start_info\n")); + DPRINTF(("shared_info_frame = 0x%lx\n", shared_info_frame)); + /* shared_info page starts its life empty. */ + + shared_info = xc_map_foreign_range(xc_handle, dom, + PAGE_SIZE, PROT_READ | PROT_WRITE, + shared_info_frame); + memset(shared_info, 0, PAGE_SIZE); + /* Mask all upcalls... */ + DPRINTF(("mask all upcalls\n")); + for (i = 0; i < MAX_VIRT_CPUS; i++) + shared_info->vcpu_data[i].evtchn_upcall_mask = 1; + munmap(shared_info, PAGE_SIZE); + + /* Send the page update requests down to the hypervisor. */ + DPRINTF(("send page update reqs down.\n")); + if (finish_mmu_updates(xc_handle, mmu)) + goto error_out; + + //DPRINTF (("call dumpit.\n")); + //dumpit(pm_handle, 0x100000>>12, tot_pages, page_array) ; + //dumpit (pm_handle, 2, 0x100, page_array); + free(mmu); + + /* we don't bother freeing anything at this point -- + * we're exiting and it is pointless + */ + return 0; + + error_out: + /* oh well we still free some things -- I oughtta nuke this */ + if (mmu != NULL) + free(mmu); + ; + return -1; +} + +int +xc_plan9_build(int xc_handle, + u32 domid, + const char *image_name, + const char *cmdline, + unsigned int control_evtchn, unsigned long flags) +{ + dom0_op_t launch_op, op; + unsigned long load_addr; + long tot_pages; + int kernel_fd = -1; + gzFile kernel_gfd = NULL; + int rc, i; + full_execution_context_t st_ctxt, *ctxt = &st_ctxt; + unsigned long virt_startinfo_addr; + + if ((tot_pages = get_tot_pages(xc_handle, domid)) < 0) { + PERROR("Could not find total pages for domain"); + return 1; + } + DPRINTF(("get_tot_pages returns %ld pages\n", tot_pages)); + + kernel_fd = open(image_name, O_RDONLY); + if (kernel_fd < 0) { + PERROR("Could not open kernel image"); + return 1; + } + + if ((kernel_gfd = gzdopen(kernel_fd, "rb")) == NULL) { + PERROR("Could not allocate decompression state for state file"); + close(kernel_fd); + return 1; + } + + DPRINTF(("get_tot_pages returns %ld pages\n", tot_pages)); + if (mlock(&st_ctxt, sizeof (st_ctxt))) { + PERROR("Unable to mlock ctxt"); + return 1; + } + + op.cmd = DOM0_GETDOMAININFO; + op.u.getdomaininfo.domain = (domid_t) domid; + op.u.getdomaininfo.ctxt = ctxt; + if ((do_dom0_op(xc_handle, &op) < 0) || + ((u32) op.u.getdomaininfo.domain != domid)) { + PERROR("Could not get info on domain"); + goto error_out; + } + DPRINTF(("get_tot_pages returns %ld pages\n", tot_pages)); + + if (!(op.u.getdomaininfo.flags & DOMFLAGS_PAUSED) + || (op.u.getdomaininfo.ctxt->pt_base != 0)) { + ERROR("Domain is already constructed"); + goto error_out; + } + + DPRINTF(("get_tot_pages returns %ld pages\n", tot_pages)); + if (setup_guestos(xc_handle, domid, kernel_gfd, tot_pages, + &virt_startinfo_addr, + &load_addr, &st_ctxt, cmdline, + op.u.getdomaininfo.shared_info_frame, + control_evtchn, flags) < 0) { + ERROR("Error constructing guest OS"); + goto error_out; + } + + /* leave the leak in here for now + if ( kernel_fd >= 0 ) + close(kernel_fd); + if( kernel_gfd ) + gzclose(kernel_gfd); + */ + ctxt->flags = 0; + + /* + * Initial register values: + * DS,ES,FS,GS = FLAT_GUESTOS_DS + * CS:EIP = FLAT_GUESTOS_CS:start_pc + * SS:ESP = FLAT_GUESTOS_DS:start_stack + * ESI = start_info + * [EAX,EBX,ECX,EDX,EDI,EBP are zero] + * EFLAGS = IF | 2 (bit 1 is reserved and should always be 1) + */ + ctxt->cpu_ctxt.ds = FLAT_GUESTOS_DS; + ctxt->cpu_ctxt.es = FLAT_GUESTOS_DS; + ctxt->cpu_ctxt.fs = FLAT_GUESTOS_DS; + ctxt->cpu_ctxt.gs = FLAT_GUESTOS_DS; + ctxt->cpu_ctxt.ss = FLAT_GUESTOS_DS; + ctxt->cpu_ctxt.cs = FLAT_GUESTOS_CS; + ctxt->cpu_ctxt.eip = load_addr; + ctxt->cpu_ctxt.eip = 0x80100020; + /* put stack at top of second page */ + ctxt->cpu_ctxt.esp = 0x80000000 + (STACKPAGE << PAGE_SHIFT); + + /* why is this set? */ + ctxt->cpu_ctxt.esi = ctxt->cpu_ctxt.esp; + ctxt->cpu_ctxt.eflags = (1 << 9) | (1 << 2); + + /* FPU is set up to default initial state. */ + memset(ctxt->fpu_ctxt, 0, sizeof (ctxt->fpu_ctxt)); + + /* Virtual IDT is empty at start-of-day. */ + for (i = 0; i < 256; i++) { + ctxt->trap_ctxt[i].vector = i; + ctxt->trap_ctxt[i].cs = FLAT_GUESTOS_CS; + } + ctxt->fast_trap_idx = 0; + + /* No LDT. */ + ctxt->ldt_ents = 0; + + /* Use the default Xen-provided GDT. */ + ctxt->gdt_ents = 0; + + /* Ring 1 stack is the initial stack. */ + /* put stack at top of second page */ + ctxt->guestos_ss = FLAT_GUESTOS_DS; + ctxt->guestos_esp = ctxt->cpu_ctxt.esp; + + /* No debugging. */ + memset(ctxt->debugreg, 0, sizeof (ctxt->debugreg)); + + /* No callback handlers. */ + ctxt->event_callback_cs = FLAT_GUESTOS_CS; + ctxt->event_callback_eip = 0; + ctxt->failsafe_callback_cs = FLAT_GUESTOS_CS; + ctxt->failsafe_callback_eip = 0; + + memset(&launch_op, 0, sizeof (launch_op)); + + launch_op.u.builddomain.domain = (domid_t) domid; + // launch_op.u.builddomain.num_vifs = 1; + launch_op.u.builddomain.ctxt = ctxt; + launch_op.cmd = DOM0_BUILDDOMAIN; + rc = do_dom0_op(xc_handle, &launch_op); + + fprintf(stderr, "RC is %d\n", rc); + return rc; + + error_out: + if (kernel_fd >= 0) + close(kernel_fd); + if (kernel_gfd) + gzclose(kernel_gfd); + + return -1; +} + +/* + * Plan 9 memory layout (initial) + * ---------------- + * | info from xen| @0 + * ---------------- + * | stack | + * ----------------<--- page 2 + * | empty | + * ---------------<---- page 5 MACHADDR (always points to machp[cpuno] + * | aliased | + * ---------------<----- page 6 CPU0MACH + * | CPU0MACH | + * ---------------- + * | empty | + * ---------------- *virt_load_addr = ehdr.e_entry (0x80100000) + * | kernel | + * | | + * ---------------- <----- page aligned boundary. + * | data | + * | | + * ---------------- + * | bss | + * ----------------<--- end of kernel (page aligned) + * | PMD cpu0pdb | + * ----------------<--- page +1 + * | PTE cpu0pte | + * ----------------<--- page (tot_pte_pages)/1024 + * | page_array | + * ---------------- <--- page (tot_pte_pages)/1024 + * | empty to TOM | + * ---------------- + */ + +static int +loadp9image(gzFile kernel_gfd, int xc_handle, u32 dom, + unsigned long *page_array, + unsigned long tot_pages, unsigned long *virt_load_addr, + unsigned long *ksize, unsigned long *symtab_addr, + unsigned long *symtab_len, + unsigned long *first_data_page, unsigned long *pdb_page) +{ + unsigned long datapage; + Exec ehdr; + + char *p; + unsigned long maxva; + int curpos, ret; + PAGE *image = 0; + unsigned long image_tot_pages = 0; + unsigned long textround; + + ret = -1; + + p = NULL; + maxva = 0; + + if (gzread(kernel_gfd, &ehdr, sizeof (Exec)) != sizeof (Exec)) { + PERROR("Error reading kernel image P9 header."); + goto out; + } + + plan9header(&ehdr); + curpos = sizeof (Exec); + + if (ehdr.magic != I_MAGIC) { + PERROR("Image does not have an P9 header."); + goto out; + } + + textround = ((ehdr.text + 0x20 + 4095) >> 12) << 12; + *first_data_page = 0x100000 + textround; + DPRINTF(("ehrd.text is 0x%lx, textround is 0x%lx\n", + ehdr.text, textround)); + + image_tot_pages = + (textround + ehdr.data + ehdr.bss + PAGE_SIZE - 1) >> PAGE_SHIFT; + DPRINTF(("tot pages is %ld\n", image_tot_pages)); + + *virt_load_addr = 0x80100000; + + if ((*virt_load_addr & (PAGE_SIZE - 1)) != 0) { + ERROR("We can only deal with page-aligned load addresses"); + goto out; + } + + if ((*virt_load_addr + (image_tot_pages << PAGE_SHIFT)) > + HYPERVISOR_VIRT_START) { + ERROR("Cannot map all domain memory without hitting Xen space"); + goto out; + } + + /* just malloc an image that is image_tot_pages in size. Then read in + * the image -- text, data, -- to page-rounded alignments. + * then copy into xen . + * this gets BSS zeroed for free + */ + DPRINTF(("Allocate %ld bytes\n", image_tot_pages * sizeof (*image))); + image = calloc(image_tot_pages, sizeof (*image)); + if (!image) + return blah("alloc data"); + /* text starts at 0x20, after the header, just like Unix long ago */ + if (gzread(kernel_gfd, &image[0].data[sizeof (Exec)], ehdr.text) < + ehdr.text) + return blah("read text"); + DPRINTF(("READ TEXT %ld bytes\n", ehdr.text)); + datapage = ((ehdr.text + sizeof (Exec)) / PAGE_SIZE) + 1; + if (gzread(kernel_gfd, image[datapage].data, ehdr.data) < ehdr.data) + return blah("read data"); + DPRINTF(("READ DATA %ld bytes\n", ehdr.data)); + + /* nice contig stuff */ + /* oops need to start at 0x100000 */ + + ret = memcpy_toguest(xc_handle, dom, + image, image_tot_pages * 4096, page_array, 0x100); + DPRINTF(("done copying kernel to guest memory\n")); + + out: + if (image) + free(image); + *pdb_page = image_tot_pages + (0x100000 >> PAGE_SHIFT); + return ret; +} diff --git a/tools/misc/xencons b/tools/misc/xencons index 7ac63aeb75..8bd3178eab 100755 --- a/tools/misc/xencons +++ b/tools/misc/xencons @@ -27,24 +27,34 @@ def __recv_from_sock(sock): while not stop: try: data = sock.recv(1024) - os.write(1, data) except socket.error, error: if error[0] != errno.EINTR: raise + else: + try: + os.write(1, data) + except os.error, error: + if error[0] != errno.EINTR: + raise os.wait() def __send_to_sock(sock): while 1: - data = os.read(0,1024) - if ord(data[0]) == ord(']')-64: - break try: - sock.send(data) - except socket.error, error: - if error[0] == errno.EPIPE: - sys.exit(0) + data = os.read(0,1024) + except os.error, error: if error[0] != errno.EINTR: raise + else: + if ord(data[0]) == ord(']')-64: + break + try: + sock.send(data) + except socket.error, error: + if error[0] == errno.EPIPE: + sys.exit(0) + if error[0] != errno.EINTR: + raise sys.exit(0) def connect(host,port): diff --git a/tools/python/xen/lowlevel/xc/xc.c b/tools/python/xen/lowlevel/xc/xc.c index 2dd8680b4f..d2b7da0eba 100644 --- a/tools/python/xen/lowlevel/xc/xc.c +++ b/tools/python/xen/lowlevel/xc/xc.c @@ -366,6 +366,33 @@ static PyObject *pyxc_linux_build(PyObject *self, return zero; } +static PyObject *pyxc_plan9_build(PyObject *self, + PyObject *args, + PyObject *kwds) +{ + XcObject *xc = (XcObject *)self; + + u32 dom; + char *image, *ramdisk = NULL, *cmdline = ""; + int control_evtchn, flags = 0; + + static char *kwd_list[] = { "dom", "control_evtchn", + "image", "ramdisk", "cmdline", "flags", + NULL }; + + if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iis|ssi", kwd_list, + &dom, &control_evtchn, + &image, &ramdisk, &cmdline, &flags) ) + return NULL; + + if ( xc_plan9_build(xc->xc_handle, dom, image, + cmdline, control_evtchn, flags) != 0 ) + return PyErr_SetFromErrno(xc_error); + + Py_INCREF(zero); + return zero; +} + static PyObject *pyxc_bvtsched_global_set(PyObject *self, PyObject *args, PyObject *kwds) @@ -889,6 +916,14 @@ static PyMethodDef pyxc_methods[] = { " state_file [str]: Name of state file. Must not currently exist.\n" " progress [int, 1]: Bool - display a running progress indication?\n\n" "Returns: [int] 0 on success; -1 on error.\n" }, + { "plan9_build", + (PyCFunction)pyxc_plan9_build, + METH_VARARGS | METH_KEYWORDS, "\n" + "Build a new Plan 9 guest OS.\n" + " dom [long]: Identifier of domain to build into.\n" + " image [str]: Name of kernel image file. May be gzipped.\n" + " cmdline [str, n/a]: Kernel parameters, if any.\n\n" + "Returns: [int] 0 on success; -1 on error.\n" }, { "linux_restore", (PyCFunction)pyxc_linux_restore, diff --git a/tools/python/xen/util/console_client.py b/tools/python/xen/util/console_client.py index 7ac63aeb75..8bd3178eab 100644 --- a/tools/python/xen/util/console_client.py +++ b/tools/python/xen/util/console_client.py @@ -27,24 +27,34 @@ def __recv_from_sock(sock): while not stop: try: data = sock.recv(1024) - os.write(1, data) except socket.error, error: if error[0] != errno.EINTR: raise + else: + try: + os.write(1, data) + except os.error, error: + if error[0] != errno.EINTR: + raise os.wait() def __send_to_sock(sock): while 1: - data = os.read(0,1024) - if ord(data[0]) == ord(']')-64: - break try: - sock.send(data) - except socket.error, error: - if error[0] == errno.EPIPE: - sys.exit(0) + data = os.read(0,1024) + except os.error, error: if error[0] != errno.EINTR: raise + else: + if ord(data[0]) == ord(']')-64: + break + try: + sock.send(data) + except socket.error, error: + if error[0] == errno.EPIPE: + sys.exit(0) + if error[0] != errno.EINTR: + raise sys.exit(0) def connect(host,port): diff --git a/tools/python/xen/xend/XendClient.py b/tools/python/xen/xend/XendClient.py index 8290165412..4e733b7fde 100644 --- a/tools/python/xen/xend/XendClient.py +++ b/tools/python/xen/xend/XendClient.py @@ -228,10 +228,11 @@ class Xend: return self.xendPost(self.domainurl(id), {'op' : 'pause' }) - def xend_domain_shutdown(self, id, reason): + def xend_domain_shutdown(self, id, reason, key=0): return self.xendPost(self.domainurl(id), {'op' : 'shutdown', - 'reason' : reason }) + 'reason' : reason, + 'key' : key }) def xend_domain_destroy(self, id, reason): return self.xendPost(self.domainurl(id), diff --git a/tools/python/xen/xend/XendDomain.py b/tools/python/xen/xend/XendDomain.py index fc53b4de03..1b01b43cfa 100644 --- a/tools/python/xen/xend/XendDomain.py +++ b/tools/python/xen/xend/XendDomain.py @@ -455,7 +455,7 @@ class XendDomain: except Exception, ex: raise XendError(str(ex)) - def domain_shutdown(self, id, reason='poweroff'): + def domain_shutdown(self, id, reason='poweroff', key=0): """Shutdown domain (nicely). - poweroff: restart according to exit code and restart mode - reboot: restart on exit @@ -474,7 +474,7 @@ class XendDomain: eserver.inject('xend.domain.shutdown', [dominfo.name, dominfo.id, reason]) if reason == 'halt': reason = 'poweroff' - val = xend.domain_shutdown(dominfo.id, reason) + val = xend.domain_shutdown(dominfo.id, reason, key) self.refresh_schedule() return val diff --git a/tools/python/xen/xend/XendDomainInfo.py b/tools/python/xen/xend/XendDomainInfo.py index 335da5e486..1a229a5599 100644 --- a/tools/python/xen/xend/XendDomainInfo.py +++ b/tools/python/xen/xend/XendDomainInfo.py @@ -1065,6 +1065,34 @@ def vm_image_linux(vm, image): vm.create_domain("linux", kernel, ramdisk, cmdline) return vm +def vm_image_plan9(vm, image): + """Create a VM for a Plan 9 image. + + name vm name + memory vm memory + image image config + + returns vm + """ + #todo: Same as for linux. Is that right? If so can unify them. + kernel = sxp.child_value(image, "kernel") + cmdline = "" + ip = sxp.child_value(image, "ip", "dhcp") + if ip: + cmdline += "ip=" + ip + root = sxp.child_value(image, "root") + if root: + cmdline += "root=" + root + args = sxp.child_value(image, "args") + if args: + cmdline += " " + args + ramdisk = sxp.child_value(image, "ramdisk", '') + vifs = vm.config_devices("vif") + vm.create_domain("plan9", kernel, ramdisk, cmdline) + return vm + + + def vm_dev_vif(vm, val, index, change=0): """Create a virtual network interface (vif). @@ -1186,6 +1214,7 @@ def vm_field_maxmem(vm, config, val, index): # Register image handlers. add_image_handler('linux', vm_image_linux) +add_image_handler('plan9', vm_image_plan9) # Register device handlers. add_device_handler('vif', vm_dev_vif) diff --git a/tools/python/xen/xend/encode.py b/tools/python/xen/xend/encode.py index 38c9351db7..48815defa9 100644 --- a/tools/python/xen/xend/encode.py +++ b/tools/python/xen/xend/encode.py @@ -14,6 +14,8 @@ import httplib import random import md5 +from xen.util.ip import _readline, _readlines + # Extract from HTML4 spec. ## The following example illustrates "multipart/form-data" ## encoding. Suppose we have the following form: @@ -122,7 +124,7 @@ def encode_multipart(d): out.write('"\r\n') out.write('Content-Type: application/octet-stream\r\n') out.write('\r\n') - for l in v.readlines(): + for l in _readlines(v): out.write(l) else: out.write('Content-Disposition: form-data; name="') diff --git a/tools/python/xen/xend/server/SrvDaemon.py b/tools/python/xen/xend/server/SrvDaemon.py index 05a0f27201..338d6e4d4a 100644 --- a/tools/python/xen/xend/server/SrvDaemon.py +++ b/tools/python/xen/xend/server/SrvDaemon.py @@ -711,14 +711,14 @@ class Daemon: raise XendError('Invalid console id') console.disconnect() - def domain_shutdown(self, dom, reason): + def domain_shutdown(self, dom, reason, key=0): """Shutdown a domain. """ dom = int(dom) ctrl = self.domainCF.getController(dom) if not ctrl: raise XendError('No domain controller: %s' % dom) - ctrl.shutdown(reason) + ctrl.shutdown(reason, key) return 0 def domain_mem_target_set(self, dom, target): diff --git a/tools/python/xen/xend/server/SrvDomain.py b/tools/python/xen/xend/server/SrvDomain.py index c06b260ce1..d73a39bff5 100644 --- a/tools/python/xen/xend/server/SrvDomain.py +++ b/tools/python/xen/xend/server/SrvDomain.py @@ -47,7 +47,8 @@ class SrvDomain(SrvDir): def op_shutdown(self, op, req): fn = FormFn(self.xd.domain_shutdown, [['dom', 'str'], - ['reason', 'str']]) + ['reason', 'str'], + ['key', 'int']]) val = fn(req.args, {'dom': self.dom.id}) req.setResponseCode(http.ACCEPTED) req.setHeader("Location", "%s/.." % req.prePathURL()) diff --git a/tools/python/xen/xend/server/domain.py b/tools/python/xen/xend/server/domain.py index 4e1baf64de..eb0dbcf48b 100644 --- a/tools/python/xen/xend/server/domain.py +++ b/tools/python/xen/xend/server/domain.py @@ -28,7 +28,8 @@ class DomainController(controller.Controller): """ reasons = {'poweroff' : 'shutdown_poweroff_t', 'reboot' : 'shutdown_reboot_t', - 'suspend' : 'shutdown_suspend_t' } + 'suspend' : 'shutdown_suspend_t', + 'sysrq' : 'shutdown_sysrq_t' } def __init__(self, factory, dom): controller.Controller.__init__(self, factory, dom) @@ -36,16 +37,19 @@ class DomainController(controller.Controller): self.addMethod(CMSG_MEM_REQUEST, 0, None) self.registerChannel() - def shutdown(self, reason): + def shutdown(self, reason, key=0): """Shutdown a domain. reason shutdown reason + key sysrq key (only if reason is 'sysrq') """ msgtype = self.reasons.get(reason) if not msgtype: raise XendError('invalid reason:' + reason) - msg = packMsg(msgtype, {}) - self.writeRequest(msg) + extra = {} + if reason == 'sysrq': extra['key'] = key + print extra + self.writeRequest(packMsg(msgtype, extra)) def mem_target_set(self, target): """Set domain memory target in pages. diff --git a/tools/python/xen/xend/server/messages.py b/tools/python/xen/xend/server/messages.py index 081dd9ce32..35f9db986e 100644 --- a/tools/python/xen/xend/server/messages.py +++ b/tools/python/xen/xend/server/messages.py @@ -197,10 +197,12 @@ CMSG_SHUTDOWN = 6 CMSG_SHUTDOWN_POWEROFF = 0 CMSG_SHUTDOWN_REBOOT = 1 CMSG_SHUTDOWN_SUSPEND = 2 +CMSG_SHUTDOWN_SYSRQ = 3 STOPCODE_shutdown = 0 STOPCODE_reboot = 1 STOPCODE_suspend = 2 +STOPCODE_sysrq = 3 shutdown_formats = { 'shutdown_poweroff_t': @@ -211,6 +213,9 @@ shutdown_formats = { 'shutdown_suspend_t': (CMSG_SHUTDOWN, CMSG_SHUTDOWN_SUSPEND), + + 'shutdown_sysrq_t': + (CMSG_SHUTDOWN, CMSG_SHUTDOWN_SYSRQ) } msg_formats.update(shutdown_formats) diff --git a/tools/python/xen/xend/sxp.py b/tools/python/xen/xend/sxp.py index 98cc303416..35b24aa8aa 100644 --- a/tools/python/xen/xend/sxp.py +++ b/tools/python/xen/xend/sxp.py @@ -17,6 +17,7 @@ import types import errno import string from StringIO import StringIO +from xen.util.ip import _readline, _readlines __all__ = [ "mime_type", @@ -713,7 +714,7 @@ def parse(io): """ pin = Parser() while 1: - buf = io.readline() + buf = _readline(io) pin.input(buf) if len(buf) == 0: break diff --git a/tools/python/xen/xm/main.py b/tools/python/xen/xm/main.py index e7454e507a..411da44106 100644 --- a/tools/python/xen/xm/main.py +++ b/tools/python/xen/xm/main.py @@ -11,7 +11,7 @@ from xen.xend import PrettyPrint from xen.xend import sxp from xen.xend.XendClient import XendError, server from xen.xend.XendClient import main as xend_client_main -from xen.xm import create, destroy, migrate, shutdown +from xen.xm import create, destroy, migrate, shutdown, sysrq from xen.xm.opts import * class Group: @@ -401,6 +401,19 @@ class ProgShutdown(Prog): xm.prog(ProgShutdown) +class ProgSysrq(Prog): + group = 'domain' + name = "sysrq" + info = """Send a sysrq to a domain.""" + + def help(self, args): + sysrq.main([args[0], '-h']) + + def main(self, args): + sysrq.main(args) + +xm.prog(ProgSysrq) + class ProgPause(Prog): group = 'domain' name = "pause" diff --git a/tools/python/xen/xm/sysrq.py b/tools/python/xen/xm/sysrq.py new file mode 100644 index 0000000000..44827af094 --- /dev/null +++ b/tools/python/xen/xm/sysrq.py @@ -0,0 +1,39 @@ +# (C) Matthew Bloch <matthew@bytemark.co.uk> 2004 + +"""Domain shutdown. +""" +import string +import sys +import time + +from xen.xend.XendClient import server +from xen.xm.opts import * + +DOM0_NAME = 'Domain-0' +DOM0_ID = '0' + +gopts = Opts(use="""[DOM] [letter] + +Sends a Linux sysrq to a domain. +""") + +gopts.opt('help', short='h', + fn=set_true, default=0, + use="Print this help.") + +def sysrq(dom, req): + server.xend_domain_shutdown(dom, 'sysrq', req) + +def main(argv): + opts = gopts + args = opts.parse(argv) + if opts.vals.help: + opts.usage() + return + + # no options for the moment + if len(args) < 1: opts.err('Missing domain') + if len(args) < 2: opts.err('Missing sysrq character') + dom = args[0] + req = ord(args[1][0]) + sysrq(dom, req) diff --git a/xen/arch/x86/Rules.mk b/xen/arch/x86/Rules.mk index bceb1982f4..d569a435c5 100644 --- a/xen/arch/x86/Rules.mk +++ b/xen/arch/x86/Rules.mk @@ -32,3 +32,20 @@ CFLAGS += -m64 -mno-red-zone -fpic -fno-reorder-blocks CFLAGS += -fno-asynchronous-unwind-tables LDFLAGS := --oformat elf64-x86-64 endif + +# Test for at least GCC v3.2.x. +gcc-ver = $(shell $(CC) -dumpversion | sed -e 's/^\(.\)\.\(.\)\.\(.\)/\$(1)/') +ifeq ($(call gcc-ver,1),1) +$(error gcc-1.x.x unsupported - upgrade to at least gcc-3.2.x) +endif +ifeq ($(call gcc-ver,1),2) +$(error gcc-2.x.x unsupported - upgrade to at least gcc-3.2.x) +endif +ifeq ($(call gcc-ver,1),3) +ifeq ($(call gcc-ver,2),0) +$(error gcc-3.0.x unsupported - upgrade to at least gcc-3.2.x) +endif +ifeq ($(call gcc-ver,2),1) +$(error gcc-3.1.x unsupported - upgrade to at least gcc-3.2.x) +endif +endif diff --git a/xen/arch/x86/boot/x86_32.S b/xen/arch/x86/boot/x86_32.S index 305c279c5e..ef568efd3a 100644 --- a/xen/arch/x86/boot/x86_32.S +++ b/xen/arch/x86/boot/x86_32.S @@ -102,15 +102,15 @@ __start: /* Initialize low and high mappings of all memory with 4MB pages */ mov $idle_pg_table-__PAGE_OFFSET,%edi - mov $0x1e3,%eax /* PRESENT+RW+A+D+4MB+GLOBAL */ + mov $0xe3,%eax /* PRESENT+RW+A+D+4MB */ 1: mov %eax,__PAGE_OFFSET>>20(%edi) /* high mapping */ stosl /* low mapping */ add $(1<<L2_PAGETABLE_SHIFT),%eax - cmp $DIRECTMAP_PHYS_END+0x1e3,%eax + cmp $DIRECTMAP_PHYS_END+0xe3,%eax jne 1b 1: stosl /* low mappings cover as much physmem as possible */ add $(1<<L2_PAGETABLE_SHIFT),%eax - cmp $__HYPERVISOR_VIRT_START+0x1e3,%eax + cmp $__HYPERVISOR_VIRT_START+0xe3,%eax jne 1b /* Initialise IDT with simple error defaults. */ diff --git a/xen/arch/x86/boot/x86_64.S b/xen/arch/x86/boot/x86_64.S index 98289c7ab6..a8253a4ce1 100644 --- a/xen/arch/x86/boot/x86_64.S +++ b/xen/arch/x86/boot/x86_64.S @@ -257,30 +257,22 @@ copy_to_user: set_intr_gate: die: machine_to_phys_mapping: -.globl copy_from_user, show_registers, __set_fixmap, do_iopl, check_descriptor +.globl copy_from_user, show_registers, do_iopl copy_from_user: show_registers: -__set_fixmap: do_iopl: -check_descriptor: -.globl set_gdt, idt_table, copy_user_generic, memcmp, idt_tables, new_thread -set_gdt: +.globl idt_table, copy_user_generic, memcmp, idt_tables, new_thread idt_table: copy_user_generic: memcmp: idt_tables: new_thread: -.globl switch_to, continue_nonidle_task, __get_user_1, paging_init, trap_init +.globl switch_to, __get_user_1, __get_user_4, __get_user_8, trap_init switch_to: -continue_nonidle_task: __get_user_1: -paging_init: -trap_init: -.globl __get_user_8, zap_low_mappings, set_debugreg,synchronise_pagetables +__get_user_4: __get_user_8: -zap_low_mappings: +trap_init: +.globl set_debugreg set_debugreg: -synchronise_pagetables: -.globl destroy_gdt -destroy_gdt: diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c index 4a01d86351..95dc9779a6 100644 --- a/xen/arch/x86/domain.c +++ b/xen/arch/x86/domain.c @@ -48,35 +48,16 @@ #define round_pgup(_p) (((_p)+(PAGE_SIZE-1))&PAGE_MASK) #define round_pgdown(_p) ((_p)&PAGE_MASK) -int hlt_counter; - -void disable_hlt(void) -{ - hlt_counter++; -} - -void enable_hlt(void) -{ - hlt_counter--; -} - -/* - * We use this if we don't have any better - * idle routine.. - */ static void default_idle(void) { - if ( hlt_counter == 0 ) - { - __cli(); - if ( !softirq_pending(smp_processor_id()) ) - safe_halt(); - else - __sti(); - } + __cli(); + if ( !softirq_pending(smp_processor_id()) ) + safe_halt(); + else + __sti(); } -void continue_cpu_idle_loop(void) +static __attribute_used__ void idle_loop(void) { int cpu = smp_processor_id(); for ( ; ; ) @@ -102,7 +83,7 @@ void startup_cpu_idle_loop(void) smp_mb(); init_idle(); - continue_cpu_idle_loop(); + idle_loop(); } static long no_idt[2]; @@ -216,20 +197,43 @@ void free_perdomain_pt(struct domain *d) free_xenheap_page((unsigned long)d->mm.perdomain_pt); } +static void continue_idle_task(struct domain *d) +{ + reset_stack_and_jump(idle_loop); +} + +static void continue_nonidle_task(struct domain *d) +{ + reset_stack_and_jump(ret_from_intr); +} + void arch_do_createdomain(struct domain *d) { - d->shared_info = (void *)alloc_xenheap_page(); - memset(d->shared_info, 0, PAGE_SIZE); - d->shared_info->arch.mfn_to_pfn_start = - virt_to_phys(&machine_to_phys_mapping[0])>>PAGE_SHIFT; - SHARE_PFN_WITH_DOMAIN(virt_to_page(d->shared_info), d); - machine_to_phys_mapping[virt_to_phys(d->shared_info) >> - PAGE_SHIFT] = INVALID_P2M_ENTRY; - - d->mm.perdomain_pt = (l1_pgentry_t *)alloc_xenheap_page(); - memset(d->mm.perdomain_pt, 0, PAGE_SIZE); - machine_to_phys_mapping[virt_to_phys(d->mm.perdomain_pt) >> - PAGE_SHIFT] = INVALID_P2M_ENTRY; +#ifdef ARCH_HAS_FAST_TRAP + SET_DEFAULT_FAST_TRAP(&d->thread); +#endif + + if ( d->id == IDLE_DOMAIN_ID ) + { + d->thread.schedule_tail = continue_idle_task; + } + else + { + d->thread.schedule_tail = continue_nonidle_task; + + d->shared_info = (void *)alloc_xenheap_page(); + memset(d->shared_info, 0, PAGE_SIZE); + d->shared_info->arch.mfn_to_pfn_start = + virt_to_phys(&machine_to_phys_mapping[0])>>PAGE_SHIFT; + SHARE_PFN_WITH_DOMAIN(virt_to_page(d->shared_info), d); + machine_to_phys_mapping[virt_to_phys(d->shared_info) >> + PAGE_SHIFT] = INVALID_P2M_ENTRY; + + d->mm.perdomain_pt = (l1_pgentry_t *)alloc_xenheap_page(); + memset(d->mm.perdomain_pt, 0, PAGE_SIZE); + machine_to_phys_mapping[virt_to_phys(d->mm.perdomain_pt) >> + PAGE_SHIFT] = INVALID_P2M_ENTRY; + } } int arch_final_setup_guestos(struct domain *d, full_execution_context_t *c) @@ -263,7 +267,6 @@ int arch_final_setup_guestos(struct domain *d, full_execution_context_t *c) sizeof(d->thread.traps)); #ifdef ARCH_HAS_FAST_TRAP - SET_DEFAULT_FAST_TRAP(&d->thread); if ( (rc = (int)set_fast_trap(d, c->fast_trap_idx)) != 0 ) return rc; #endif @@ -328,9 +331,6 @@ void new_thread(struct domain *d, __save_flags(ec->eflags); ec->eflags |= X86_EFLAGS_IF; - - /* No fast trap at start of day. */ - SET_DEFAULT_FAST_TRAP(&d->thread); } @@ -427,6 +427,8 @@ long do_iopl(domid_t domain, unsigned int new_io_pl) return 0; } +#endif + unsigned long hypercall_create_continuation( unsigned int op, unsigned int nr_args, ...) { @@ -448,11 +450,15 @@ unsigned long hypercall_create_continuation( else { ec = get_execution_context(); +#if defined(__i386__) ec->eax = op; ec->eip -= 2; /* re-execute 'int 0x82' */ for ( i = 0, preg = &ec->ebx; i < nr_args; i++, preg++ ) *preg = va_arg(args, unsigned long); +#else + preg = NULL; /* XXX x86/64 */ +#endif } va_end(args); @@ -460,9 +466,6 @@ unsigned long hypercall_create_continuation( return op; } -#endif - - static void relinquish_list(struct domain *d, struct list_head *list) { struct list_head *ent; diff --git a/xen/arch/x86/setup.c b/xen/arch/x86/setup.c index cf6f7980e1..d2109f4fb8 100644 --- a/xen/arch/x86/setup.c +++ b/xen/arch/x86/setup.c @@ -328,6 +328,8 @@ void __init start_of_day(void) sort_exception_tables(); + arch_do_createdomain(current); + /* Tell the PCI layer not to allocate too close to the RAM area.. */ low_mem_size = ((max_page << PAGE_SHIFT) + 0xfffff) & ~0xfffff; if ( low_mem_size > pci_mem_start ) pci_mem_start = low_mem_size; diff --git a/xen/arch/x86/shadow.c b/xen/arch/x86/shadow.c index 77b09551d9..aa4afc3cda 100644 --- a/xen/arch/x86/shadow.c +++ b/xen/arch/x86/shadow.c @@ -517,10 +517,10 @@ static void shadow_map_l1_into_current_l2(unsigned long va) mk_l2_pgentry(spde); gpl1e = (unsigned long *) &(linear_pg_table[ - (va>>PAGE_SHIFT) & ~(ENTRIES_PER_L1_PAGETABLE-1)]); + (va>>L1_PAGETABLE_SHIFT) & (ENTRIES_PER_L1_PAGETABLE-1)]); - spl1e = (unsigned long *) &shadow_linear_pg_table[ - (va>>PAGE_SHIFT) & ~(ENTRIES_PER_L1_PAGETABLE-1)]; + spl1e = (unsigned long *) &(shadow_linear_pg_table[ + (va>>L1_PAGETABLE_SHIFT) & (ENTRIES_PER_L1_PAGETABLE-1)]); for ( i = 0; i < ENTRIES_PER_L1_PAGETABLE; i++ ) l1pte_propagate_from_guest(m, &gpl1e[i], &spl1e[i]); diff --git a/xen/arch/x86/smpboot.c b/xen/arch/x86/smpboot.c index 05d49a27d0..991b5c577a 100644 --- a/xen/arch/x86/smpboot.c +++ b/xen/arch/x86/smpboot.c @@ -662,10 +662,6 @@ static void __init do_boot_cpu (int apicid) map_cpu_to_boot_apicid(cpu, apicid); -#if defined(__i386__) - SET_DEFAULT_FAST_TRAP(&idle->thread); -#endif - idle_task[cpu] = idle; /* start_eip had better be page-aligned! */ diff --git a/xen/arch/x86/traps.c b/xen/arch/x86/traps.c index 842de24582..6837a143d3 100644 --- a/xen/arch/x86/traps.c +++ b/xen/arch/x86/traps.c @@ -981,4 +981,10 @@ unsigned long do_get_debugreg(int reg) return current->thread.debugreg[reg]; } +#else + +asmlinkage void fatal_trap(int trapnr, struct xen_regs *regs) +{ +} + #endif /* __i386__ */ diff --git a/xen/arch/x86/x86_32/entry.S b/xen/arch/x86/x86_32/entry.S index c85d84c649..d3df231fbb 100644 --- a/xen/arch/x86/x86_32/entry.S +++ b/xen/arch/x86/x86_32/entry.S @@ -56,7 +56,7 @@ #include <xen/config.h> #include <xen/errno.h> #include <xen/softirq.h> -#include <asm/x86_32/asm_defns.h> +#include <asm/asm_defns.h> #include <public/xen.h> #define GET_CURRENT(reg) \ @@ -65,10 +65,6 @@ andl $~3,reg; \ movl (reg),reg; -ENTRY(continue_nonidle_task) - GET_CURRENT(%ebx) - jmp test_all_events - ALIGN restore_all_guest: testb $TF_failsafe_return,DOMAIN_thread_flags(%ebx) diff --git a/xen/arch/x86/x86_32/mm.c b/xen/arch/x86/x86_32/mm.c index ed95ca77e9..c22d527ac7 100644 --- a/xen/arch/x86/x86_32/mm.c +++ b/xen/arch/x86/x86_32/mm.c @@ -59,11 +59,13 @@ void __init paging_init(void) void *ioremap_pt; int i; - /* Idle page table 1:1 maps the first part of physical memory. */ - for ( i = 0; i < DOMAIN_ENTRIES_PER_L2_PAGETABLE; i++ ) - idle_pg_table[i] = - mk_l2_pgentry((i << L2_PAGETABLE_SHIFT) | - __PAGE_HYPERVISOR | _PAGE_PSE); + /* Xen heap mappings can be GLOBAL. */ + if ( cpu_has_pge ) + { + for ( i = 0; i < DIRECTMAP_PHYS_END; i += (1 << L2_PAGETABLE_SHIFT) ) + ((unsigned long *)idle_pg_table) + [(i + PAGE_OFFSET) >> L2_PAGETABLE_SHIFT] |= _PAGE_GLOBAL; + } /* Create page table for ioremap(). */ ioremap_pt = (void *)alloc_xenheap_page(); @@ -86,7 +88,6 @@ void __init paging_init(void) /* Set up linear page table mapping. */ idle_pg_table[LINEAR_PT_VIRT_START >> L2_PAGETABLE_SHIFT] = mk_l2_pgentry(__pa(idle_pg_table) | __PAGE_HYPERVISOR); - } void __init zap_low_mappings(void) diff --git a/xen/arch/x86/x86_64/asm-offsets.c b/xen/arch/x86/x86_64/asm-offsets.c new file mode 100644 index 0000000000..2e6c3b396e --- /dev/null +++ b/xen/arch/x86/x86_64/asm-offsets.c @@ -0,0 +1,71 @@ +/* + * Generate definitions needed by assembly language modules. + * This code generates raw asm output which is post-processed + * to extract and format the required data. + */ + +#include <xen/sched.h> + +#define DEFINE(_sym, _val) \ + __asm__ __volatile__ ( "\n->" #_sym " %0 " #_val : : "i" (_val) ) +#define BLANK() \ + __asm__ __volatile__ ( "\n->" : : ) +#define OFFSET(_sym, _str, _mem) \ + DEFINE(_sym, offsetof(_str, _mem)); + +void __dummy__(void) +{ + OFFSET(XREGS_r15, struct xen_regs, r15); + OFFSET(XREGS_r14, struct xen_regs, r14); + OFFSET(XREGS_r13, struct xen_regs, r13); + OFFSET(XREGS_r12, struct xen_regs, r12); + OFFSET(XREGS_rbp, struct xen_regs, rbp); + OFFSET(XREGS_rbx, struct xen_regs, rbx); + OFFSET(XREGS_r11, struct xen_regs, r11); + OFFSET(XREGS_r10, struct xen_regs, r10); + OFFSET(XREGS_r9, struct xen_regs, r9); + OFFSET(XREGS_r8, struct xen_regs, r8); + OFFSET(XREGS_rax, struct xen_regs, rax); + OFFSET(XREGS_rcx, struct xen_regs, rcx); + OFFSET(XREGS_rdx, struct xen_regs, rdx); + OFFSET(XREGS_rsi, struct xen_regs, rsi); + OFFSET(XREGS_rdi, struct xen_regs, rdi); + OFFSET(XREGS_orig_rax, struct xen_regs, orig_rax); + OFFSET(XREGS_rip, struct xen_regs, rip); + OFFSET(XREGS_cs, struct xen_regs, cs); + OFFSET(XREGS_eflags, struct xen_regs, eflags); + OFFSET(XREGS_rsp, struct xen_regs, rsp); + OFFSET(XREGS_ss, struct xen_regs, ss); + BLANK(); + + OFFSET(DOMAIN_processor, struct domain, processor); + OFFSET(DOMAIN_shared_info, struct domain, shared_info); + OFFSET(DOMAIN_event_sel, struct domain, thread.event_selector); + OFFSET(DOMAIN_event_addr, struct domain, thread.event_address); + OFFSET(DOMAIN_failsafe_sel, struct domain, thread.failsafe_selector); + OFFSET(DOMAIN_failsafe_addr, struct domain, thread.failsafe_address); + OFFSET(DOMAIN_trap_bounce, struct domain, thread.trap_bounce); + OFFSET(DOMAIN_thread_flags, struct domain, thread.flags); + BLANK(); + + OFFSET(SHINFO_upcall_pending, shared_info_t, + vcpu_data[0].evtchn_upcall_pending); + OFFSET(SHINFO_upcall_mask, shared_info_t, + vcpu_data[0].evtchn_upcall_mask); + BLANK(); + + OFFSET(TRAPBOUNCE_error_code, struct trap_bounce, error_code); + OFFSET(TRAPBOUNCE_cr2, struct trap_bounce, cr2); + OFFSET(TRAPBOUNCE_flags, struct trap_bounce, flags); + OFFSET(TRAPBOUNCE_cs, struct trap_bounce, cs); + OFFSET(TRAPBOUNCE_eip, struct trap_bounce, eip); + BLANK(); + + OFFSET(MULTICALL_op, multicall_entry_t, op); + OFFSET(MULTICALL_arg0, multicall_entry_t, args[0]); + OFFSET(MULTICALL_arg1, multicall_entry_t, args[1]); + OFFSET(MULTICALL_arg2, multicall_entry_t, args[2]); + OFFSET(MULTICALL_arg3, multicall_entry_t, args[3]); + OFFSET(MULTICALL_arg4, multicall_entry_t, args[4]); + OFFSET(MULTICALL_result, multicall_entry_t, args[5]); +} diff --git a/xen/arch/x86/x86_64/mm.c b/xen/arch/x86/x86_64/mm.c new file mode 100644 index 0000000000..c7bcb17805 --- /dev/null +++ b/xen/arch/x86/x86_64/mm.c @@ -0,0 +1,455 @@ +/****************************************************************************** + * arch/x86/x86_64/mm.c + * + * Modifications to Linux original are copyright (c) 2004, K A Fraser + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <xen/config.h> +#include <xen/lib.h> +#include <xen/init.h> +#include <xen/mm.h> +#include <asm/page.h> +#include <asm/flushtlb.h> +#include <asm/fixmap.h> +#include <asm/domain_page.h> + +static inline void set_pte_phys(unsigned long vaddr, + l1_pgentry_t entry) +{ + l4_pgentry_t *l4ent; + l3_pgentry_t *l3ent; + l2_pgentry_t *l2ent; + l1_pgentry_t *l1ent; + + l4ent = &idle_pg_table[l4_table_offset(vaddr)]; + l3ent = l4_pgentry_to_l3(*l4ent) + l3_table_offset(vaddr); + l2ent = l3_pgentry_to_l2(*l3ent) + l2_table_offset(vaddr); + l1ent = l2_pgentry_to_l1(*l2ent) + l1_table_offset(vaddr); + *l1ent = entry; + + /* It's enough to flush this one mapping. */ + __flush_tlb_one(vaddr); +} + + +void __set_fixmap(enum fixed_addresses idx, + l1_pgentry_t entry) +{ + unsigned long address = fix_to_virt(idx); + + if ( likely(idx < __end_of_fixed_addresses) ) + set_pte_phys(address, entry); + else + printk("Invalid __set_fixmap\n"); +} + + +void __init paging_init(void) +{ + void *ioremap_pt; + int i; + + /* Create page table for ioremap(). */ + ioremap_pt = (void *)alloc_xenheap_page(); + clear_page(ioremap_pt); + idle_pg_table[IOREMAP_VIRT_START >> L2_PAGETABLE_SHIFT] = + mk_l2_pgentry(__pa(ioremap_pt) | __PAGE_HYPERVISOR); + + /* Create read-only mapping of MPT for guest-OS use. */ + idle_pg_table[RO_MPT_VIRT_START >> L2_PAGETABLE_SHIFT] = + mk_l2_pgentry(l2_pgentry_val( + idle_pg_table[RDWR_MPT_VIRT_START >> L2_PAGETABLE_SHIFT]) & + ~_PAGE_RW); + + /* Set up mapping cache for domain pages. */ + mapcache = (unsigned long *)alloc_xenheap_page(); + clear_page(mapcache); + idle_pg_table[MAPCACHE_VIRT_START >> L2_PAGETABLE_SHIFT] = + mk_l2_pgentry(__pa(mapcache) | __PAGE_HYPERVISOR); + + /* Set up linear page table mapping. */ + idle_pg_table[LINEAR_PT_VIRT_START >> L2_PAGETABLE_SHIFT] = + mk_l2_pgentry(__pa(idle_pg_table) | __PAGE_HYPERVISOR); + +} + +void __init zap_low_mappings(void) +{ + idle_pg_table[0] = 0; +} + + +/* + * Allows shooting down of borrowed page-table use on specific CPUs. + * Specifically, we borrow page tables when running the idle domain. + */ +static void __synchronise_pagetables(void *mask) +{ + struct domain *d = current; + if ( ((unsigned long)mask & (1<<d->processor)) && is_idle_task(d) ) + write_ptbase(&d->mm); +} +void synchronise_pagetables(unsigned long cpu_mask) +{ + __synchronise_pagetables((void *)cpu_mask); + smp_call_function(__synchronise_pagetables, (void *)cpu_mask, 1, 1); +} + +long do_stack_switch(unsigned long ss, unsigned long esp) +{ + int nr = smp_processor_id(); + struct tss_struct *t = &init_tss[nr]; + + /* We need to do this check as we load and use SS on guest's behalf. */ + if ( (ss & 3) == 0 ) + return -EPERM; + + current->thread.guestos_ss = ss; + current->thread.guestos_sp = esp; + t->ss1 = ss; + t->esp1 = esp; + + return 0; +} + + +/* Returns TRUE if given descriptor is valid for GDT or LDT. */ +int check_descriptor(unsigned long *d) +{ + unsigned long base, limit, a = d[0], b = d[1]; + + /* A not-present descriptor will always fault, so is safe. */ + if ( !(b & _SEGMENT_P) ) + goto good; + + /* + * We don't allow a DPL of zero. There is no legitimate reason for + * specifying DPL==0, and it gets rather dangerous if we also accept call + * gates (consider a call gate pointing at another guestos descriptor with + * DPL 0 -- this would get the OS ring-0 privileges). + */ + if ( (b & _SEGMENT_DPL) == 0 ) + goto bad; + + if ( !(b & _SEGMENT_S) ) + { + /* + * System segment: + * 1. Don't allow interrupt or trap gates as they belong in the IDT. + * 2. Don't allow TSS descriptors or task gates as we don't + * virtualise x86 tasks. + * 3. Don't allow LDT descriptors because they're unnecessary and + * I'm uneasy about allowing an LDT page to contain LDT + * descriptors. In any case, Xen automatically creates the + * required descriptor when reloading the LDT register. + * 4. We allow call gates but they must not jump to a private segment. + */ + + /* Disallow everything but call gates. */ + if ( (b & _SEGMENT_TYPE) != 0xc00 ) + goto bad; + + /* Can't allow far jump to a Xen-private segment. */ + if ( !VALID_CODESEL(a>>16) ) + goto bad; + + /* Reserved bits must be zero. */ + if ( (b & 0xe0) != 0 ) + goto bad; + + /* No base/limit check is needed for a call gate. */ + goto good; + } + + /* Check that base is at least a page away from Xen-private area. */ + base = (b&(0xff<<24)) | ((b&0xff)<<16) | (a>>16); + if ( base >= (PAGE_OFFSET - PAGE_SIZE) ) + goto bad; + + /* Check and truncate the limit if necessary. */ + limit = (b&0xf0000) | (a&0xffff); + limit++; /* We add one because limit is inclusive. */ + if ( (b & _SEGMENT_G) ) + limit <<= 12; + + if ( (b & (_SEGMENT_CODE | _SEGMENT_EC)) == _SEGMENT_EC ) + { + /* + * Grows-down limit check. + * NB. limit == 0xFFFFF provides no access (if G=1). + * limit == 0x00000 provides 4GB-4kB access (if G=1). + */ + if ( (base + limit) > base ) + { + limit = -(base & PAGE_MASK); + goto truncate; + } + } + else + { + /* + * Grows-up limit check. + * NB. limit == 0xFFFFF provides 4GB access (if G=1). + * limit == 0x00000 provides 4kB access (if G=1). + */ + if ( ((base + limit) <= base) || + ((base + limit) > PAGE_OFFSET) ) + { + limit = PAGE_OFFSET - base; + truncate: + if ( !(b & _SEGMENT_G) ) + goto bad; /* too dangerous; too hard to work out... */ + limit = (limit >> 12) - 1; + d[0] &= ~0x0ffff; d[0] |= limit & 0x0ffff; + d[1] &= ~0xf0000; d[1] |= limit & 0xf0000; + } + } + + good: + return 1; + bad: + return 0; +} + + +void destroy_gdt(struct domain *d) +{ + int i; + unsigned long pfn; + + for ( i = 0; i < 16; i++ ) + { + if ( (pfn = l1_pgentry_to_pagenr(d->mm.perdomain_pt[i])) != 0 ) + put_page_and_type(&frame_table[pfn]); + d->mm.perdomain_pt[i] = mk_l1_pgentry(0); + } +} + + +long set_gdt(struct domain *d, + unsigned long *frames, + unsigned int entries) +{ + /* NB. There are 512 8-byte entries per GDT page. */ + int i = 0, nr_pages = (entries + 511) / 512; + struct desc_struct *vgdt; + unsigned long pfn; + + /* Check the first page in the new GDT. */ + if ( (pfn = frames[0]) >= max_page ) + goto fail; + + /* The first page is special because Xen owns a range of entries in it. */ + if ( !get_page_and_type(&frame_table[pfn], d, PGT_gdt_page) ) + { + /* GDT checks failed: try zapping the Xen reserved entries. */ + if ( !get_page_and_type(&frame_table[pfn], d, PGT_writable_page) ) + goto fail; + vgdt = map_domain_mem(pfn << PAGE_SHIFT); + memset(vgdt + FIRST_RESERVED_GDT_ENTRY, 0, + NR_RESERVED_GDT_ENTRIES*8); + unmap_domain_mem(vgdt); + put_page_and_type(&frame_table[pfn]); + + /* Okay, we zapped the entries. Now try the GDT checks again. */ + if ( !get_page_and_type(&frame_table[pfn], d, PGT_gdt_page) ) + goto fail; + } + + /* Check the remaining pages in the new GDT. */ + for ( i = 1; i < nr_pages; i++ ) + if ( ((pfn = frames[i]) >= max_page) || + !get_page_and_type(&frame_table[pfn], d, PGT_gdt_page) ) + goto fail; + + /* Copy reserved GDT entries to the new GDT. */ + vgdt = map_domain_mem(frames[0] << PAGE_SHIFT); + memcpy(vgdt + FIRST_RESERVED_GDT_ENTRY, + gdt_table + FIRST_RESERVED_GDT_ENTRY, + NR_RESERVED_GDT_ENTRIES*8); + unmap_domain_mem(vgdt); + + /* Tear down the old GDT. */ + destroy_gdt(d); + + /* Install the new GDT. */ + for ( i = 0; i < nr_pages; i++ ) + d->mm.perdomain_pt[i] = + mk_l1_pgentry((frames[i] << PAGE_SHIFT) | __PAGE_HYPERVISOR); + + SET_GDT_ADDRESS(d, GDT_VIRT_START); + SET_GDT_ENTRIES(d, entries); + + return 0; + + fail: + while ( i-- > 0 ) + put_page_and_type(&frame_table[frames[i]]); + return -EINVAL; +} + + +long do_set_gdt(unsigned long *frame_list, unsigned int entries) +{ + int nr_pages = (entries + 511) / 512; + unsigned long frames[16]; + long ret; + + if ( (entries <= LAST_RESERVED_GDT_ENTRY) || (entries > 8192) ) + return -EINVAL; + + if ( copy_from_user(frames, frame_list, nr_pages * sizeof(unsigned long)) ) + return -EFAULT; + + if ( (ret = set_gdt(current, frames, entries)) == 0 ) + { + local_flush_tlb(); + __asm__ __volatile__ ("lgdt %0" : "=m" (*current->mm.gdt)); + } + + return ret; +} + + +long do_update_descriptor( + unsigned long pa, unsigned long word1, unsigned long word2) +{ + unsigned long *gdt_pent, pfn = pa >> PAGE_SHIFT, d[2]; + struct pfn_info *page; + long ret = -EINVAL; + + d[0] = word1; + d[1] = word2; + + if ( (pa & 7) || (pfn >= max_page) || !check_descriptor(d) ) + return -EINVAL; + + page = &frame_table[pfn]; + if ( unlikely(!get_page(page, current)) ) + return -EINVAL; + + /* Check if the given frame is in use in an unsafe context. */ + switch ( page->u.inuse.type_info & PGT_type_mask ) + { + case PGT_gdt_page: + /* Disallow updates of Xen-reserved descriptors in the current GDT. */ + if ( (l1_pgentry_to_pagenr(current->mm.perdomain_pt[0]) == pfn) && + (((pa&(PAGE_SIZE-1))>>3) >= FIRST_RESERVED_GDT_ENTRY) && + (((pa&(PAGE_SIZE-1))>>3) <= LAST_RESERVED_GDT_ENTRY) ) + goto out; + if ( unlikely(!get_page_type(page, PGT_gdt_page)) ) + goto out; + break; + case PGT_ldt_page: + if ( unlikely(!get_page_type(page, PGT_ldt_page)) ) + goto out; + break; + default: + if ( unlikely(!get_page_type(page, PGT_writable_page)) ) + goto out; + break; + } + + /* All is good so make the update. */ + gdt_pent = map_domain_mem(pa); + memcpy(gdt_pent, d, 8); + unmap_domain_mem(gdt_pent); + + put_page_type(page); + + ret = 0; /* success */ + + out: + put_page(page); + return ret; +} + +#ifdef MEMORY_GUARD + +void *memguard_init(void *heap_start) +{ + l1_pgentry_t *l1; + int i, j; + + /* Round the allocation pointer up to a page boundary. */ + heap_start = (void *)(((unsigned long)heap_start + (PAGE_SIZE-1)) & + PAGE_MASK); + + /* Memory guarding is incompatible with super pages. */ + for ( i = 0; i < (xenheap_phys_end >> L2_PAGETABLE_SHIFT); i++ ) + { + l1 = (l1_pgentry_t *)heap_start; + heap_start = (void *)((unsigned long)heap_start + PAGE_SIZE); + for ( j = 0; j < ENTRIES_PER_L1_PAGETABLE; j++ ) + l1[j] = mk_l1_pgentry((i << L2_PAGETABLE_SHIFT) | + (j << L1_PAGETABLE_SHIFT) | + __PAGE_HYPERVISOR); + idle_pg_table[i] = idle_pg_table[i + l2_table_offset(PAGE_OFFSET)] = + mk_l2_pgentry(virt_to_phys(l1) | __PAGE_HYPERVISOR); + } + + return heap_start; +} + +static void __memguard_change_range(void *p, unsigned long l, int guard) +{ + l1_pgentry_t *l1; + l2_pgentry_t *l2; + unsigned long _p = (unsigned long)p; + unsigned long _l = (unsigned long)l; + + /* Ensure we are dealing with a page-aligned whole number of pages. */ + ASSERT((_p&PAGE_MASK) != 0); + ASSERT((_l&PAGE_MASK) != 0); + ASSERT((_p&~PAGE_MASK) == 0); + ASSERT((_l&~PAGE_MASK) == 0); + + while ( _l != 0 ) + { + l2 = &idle_pg_table[l2_table_offset(_p)]; + l1 = l2_pgentry_to_l1(*l2) + l1_table_offset(_p); + if ( guard ) + *l1 = mk_l1_pgentry(l1_pgentry_val(*l1) & ~_PAGE_PRESENT); + else + *l1 = mk_l1_pgentry(l1_pgentry_val(*l1) | _PAGE_PRESENT); + _p += PAGE_SIZE; + _l -= PAGE_SIZE; + } +} + +void memguard_guard_range(void *p, unsigned long l) +{ + __memguard_change_range(p, l, 1); + local_flush_tlb(); +} + +void memguard_unguard_range(void *p, unsigned long l) +{ + __memguard_change_range(p, l, 0); +} + +int memguard_is_guarded(void *p) +{ + l1_pgentry_t *l1; + l2_pgentry_t *l2; + unsigned long _p = (unsigned long)p; + l2 = &idle_pg_table[l2_table_offset(_p)]; + l1 = l2_pgentry_to_l1(*l2) + l1_table_offset(_p); + return !(l1_pgentry_val(*l1) & _PAGE_PRESENT); +} + +#endif diff --git a/xen/arch/x86/x86_64/xen.lds b/xen/arch/x86/x86_64/xen.lds index 4763fdf55a..8a6b3a27ac 100644 --- a/xen/arch/x86/x86_64/xen.lds +++ b/xen/arch/x86/x86_64/xen.lds @@ -28,6 +28,11 @@ SECTIONS __ex_table : { *(__ex_table) } :text __stop___ex_table = .; + . = ALIGN(16); /* Pre-exception table */ + __start___pre_ex_table = .; + __pre_ex_table : { *(__pre_ex_table) } :text + __stop___pre_ex_table = .; + __start___ksymtab = .; /* Kernel symbol table */ __ksymtab : { *(__ksymtab) } :text __stop___ksymtab = .; diff --git a/xen/common/domain.c b/xen/common/domain.c index d4a97d307a..ed18817cec 100644 --- a/xen/common/domain.c +++ b/xen/common/domain.c @@ -47,20 +47,21 @@ struct domain *do_createdomain(domid_t dom_id, unsigned int cpu) /* Per-domain PCI-device list. */ spin_lock_init(&d->pcidev_lock); INIT_LIST_HEAD(&d->pcidev_list); + + if ( (d->id != IDLE_DOMAIN_ID) && + ((init_event_channels(d) != 0) || (grant_table_create(d) != 0)) ) + { + destroy_event_channels(d); + free_domain_struct(d); + return NULL; + } + + arch_do_createdomain(d); + + sched_add_domain(d); if ( d->id != IDLE_DOMAIN_ID ) { - if ( (init_event_channels(d) != 0) || (grant_table_create(d) != 0) ) - { - destroy_event_channels(d); - free_domain_struct(d); - return NULL; - } - - arch_do_createdomain(d); - - sched_add_domain(d); - write_lock(&domlist_lock); pd = &domain_list; /* NB. domain_list maintained in order of dom_id. */ for ( pd = &domain_list; *pd != NULL; pd = &(*pd)->next_list ) @@ -72,10 +73,6 @@ struct domain *do_createdomain(domid_t dom_id, unsigned int cpu) domain_hash[DOMAIN_HASH(dom_id)] = d; write_unlock(&domlist_lock); } - else - { - sched_add_domain(d); - } return d; } diff --git a/xen/common/physdev.c b/xen/common/physdev.c index 728a8fe07f..a2559e5223 100644 --- a/xen/common/physdev.c +++ b/xen/common/physdev.c @@ -742,7 +742,8 @@ void physdev_init_dom0(struct domain *p) * * In Linux2.6 we set pcibios_scan_all_fns(). */ - if ( dev->hdr_type != PCI_HEADER_TYPE_NORMAL ) + if ( (dev->hdr_type != PCI_HEADER_TYPE_NORMAL) && + (dev->hdr_type != PCI_HEADER_TYPE_CARDBUS) ) continue; pdev = xmalloc(sizeof(phys_dev_t)); pdev->dev = dev; diff --git a/xen/include/asm-x86/asm_defns.h b/xen/include/asm-x86/asm_defns.h new file mode 100644 index 0000000000..0fb3e44727 --- /dev/null +++ b/xen/include/asm-x86/asm_defns.h @@ -0,0 +1,18 @@ + +#ifndef __X86_ASM_DEFNS_H__ +#define __X86_ASM_DEFNS_H__ + +/* NB. Auto-generated from arch/.../asm-offsets.c */ +#include <asm/asm-offsets.h> +#include <asm/processor.h> + +#define __STR(x) #x +#define STR(x) __STR(x) + +#ifdef __x86_64__ +#include <asm/x86_64/asm_defns.h> +#else +#include <asm/x86_32/asm_defns.h> +#endif + +#endif /* __X86_ASM_DEFNS_H__ */ diff --git a/xen/include/asm-x86/irq.h b/xen/include/asm-x86/irq.h index b07fef7809..2779282659 100644 --- a/xen/include/asm-x86/irq.h +++ b/xen/include/asm-x86/irq.h @@ -5,7 +5,7 @@ #include <xen/config.h> #include <asm/atomic.h> -#include <asm/x86_32/asm_defns.h> +#include <asm/asm_defns.h> extern void disable_irq(unsigned int); extern void disable_irq_nosync(unsigned int); diff --git a/xen/include/asm-x86/multicall.h b/xen/include/asm-x86/multicall.h index e1a7770354..d03ac9ffb1 100644 --- a/xen/include/asm-x86/multicall.h +++ b/xen/include/asm-x86/multicall.h @@ -5,7 +5,13 @@ #ifndef __ASM_X86_MULTICALL_H__ #define __ASM_X86_MULTICALL_H__ -#include <asm-x86/x86_32/asm_defns.h> +#include <asm/asm_defns.h> + +#ifdef __x86_64__ + +#define do_multicall_call(_call) BUG() + +#else #define do_multicall_call(_call) \ do { \ @@ -23,4 +29,6 @@ : : "b" (_call) : "eax", "ecx", "edx" ); \ } while ( 0 ) +#endif + #endif /* __ASM_X86_MULTICALL_H__ */ diff --git a/xen/include/asm-x86/processor.h b/xen/include/asm-x86/processor.h index c5ccb59fa3..ae5b13b7d1 100644 --- a/xen/include/asm-x86/processor.h +++ b/xen/include/asm-x86/processor.h @@ -254,18 +254,18 @@ static inline unsigned int cpuid_edx(unsigned int op) }) #define write_cr0(x) \ - __asm__("mov"__OS" %0,%%cr0": :"r" (x)); + __asm__("mov"__OS" %0,%%cr0": :"r" ((unsigned long)x)); #define read_cr4() ({ \ - unsigned int __dummy; \ + unsigned long __dummy; \ __asm__( \ - "movl %%cr4,%0\n\t" \ + "mov"__OS" %%cr4,%0\n\t" \ :"=r" (__dummy)); \ __dummy; \ }) #define write_cr4(x) \ - __asm__("movl %0,%%cr4": :"r" (x)); + __asm__("mov"__OS" %0,%%cr4": :"r" ((unsigned long)x)); /* * Save the cr4 feature set we're using (ie @@ -290,7 +290,7 @@ static inline void clear_in_cr4 (unsigned long mask) mmu_cr4_features &= ~mask; __asm__("mov"__OS" %%cr4,%%"__OP"ax\n\t" "and"__OS" %0,%%"__OP"ax\n\t" - "movl"__OS" %%"__OP"ax,%%cr4\n" + "mov"__OS" %%"__OP"ax,%%cr4\n" : : "irg" (~mask) :"ax"); } @@ -399,6 +399,8 @@ struct thread_struct { /* general user-visible register state */ execution_context_t user_ctxt; + void (*schedule_tail) (struct domain *); + /* * Return vectors pushed to us by guest OS. * The stack frame for events is exactly that of an x86 hardware interrupt. @@ -456,14 +458,10 @@ extern struct desc_struct *idt_tables[]; long set_fast_trap(struct domain *p, int idx); -#define INIT_THREAD { fast_trap_idx: 0x20 } - -#elif defined(__x86_64__) +#endif #define INIT_THREAD { 0 } -#endif /* __x86_64__ */ - extern int gpf_emulate_4gb(struct xen_regs *regs); struct mm_struct { diff --git a/xen/include/asm-x86/system.h b/xen/include/asm-x86/system.h index e2c961e360..18854edc3f 100644 --- a/xen/include/asm-x86/system.h +++ b/xen/include/asm-x86/system.h @@ -271,13 +271,6 @@ static inline int local_irq_is_enabled(void) return !!(flags & (1<<9)); /* EFLAGS_IF */ } -/* - * disable hlt during certain critical i/o operations - */ -#define HAVE_DISABLE_HLT -void disable_hlt(void); -void enable_hlt(void); - #define BROKEN_ACPI_Sx 0x0001 #define BROKEN_INIT_AFTER_S1 0x0002 diff --git a/xen/include/asm-x86/uaccess.h b/xen/include/asm-x86/uaccess.h index 52a8b25c56..46c02ecef4 100644 --- a/xen/include/asm-x86/uaccess.h +++ b/xen/include/asm-x86/uaccess.h @@ -1,6 +1,32 @@ +#ifndef __X86_UACCESS_H__ +#define __X86_UACCESS_H__ + #ifdef __x86_64__ #include <asm/x86_64/uaccess.h> #else #include <asm/x86_32/uaccess.h> #endif + +/* + * The exception table consists of pairs of addresses: the first is the + * address of an instruction that is allowed to fault, and the second is + * the address at which the program should continue. No registers are + * modified, so it is entirely up to the continuation code to figure out + * what to do. + * + * All the routines below use bits of fixup code that are out of line + * with the main instruction path. This means when everything is well, + * we don't even have to jump over them. Further, they do not intrude + * on our cache or tlb entries. + */ + +struct exception_table_entry +{ + unsigned long insn, fixup; +}; + +extern unsigned long search_exception_table(unsigned long); +extern void sort_exception_tables(void); + +#endif /* __X86_UACCESS_H__ */ diff --git a/xen/include/asm-x86/x86_32/asm_defns.h b/xen/include/asm-x86/x86_32/asm_defns.h index 8231bb2dec..e11ea34964 100644 --- a/xen/include/asm-x86/x86_32/asm_defns.h +++ b/xen/include/asm-x86/x86_32/asm_defns.h @@ -1,12 +1,5 @@ -#ifndef __ASM_DEFNS_H__ -#define __ASM_DEFNS_H__ - -/* NB. Auto-generated from arch/.../asm-offsets.c */ -#include <asm/asm-offsets.h> -#include <asm/processor.h> - -#define __STR(x) #x -#define STR(x) __STR(x) +#ifndef __X86_32_ASM_DEFNS_H__ +#define __X86_32_ASM_DEFNS_H__ /* Maybe auto-generate the following two cases (quoted vs. unquoted). */ #ifndef __ASSEMBLY__ @@ -85,4 +78,4 @@ #endif -#endif /* __ASM_DEFNS_H__ */ +#endif /* __X86_32_ASM_DEFNS_H__ */ diff --git a/xen/include/asm-x86/x86_32/current.h b/xen/include/asm-x86/x86_32/current.h index 3450cd02cc..2c76a133aa 100644 --- a/xen/include/asm-x86/x86_32/current.h +++ b/xen/include/asm-x86/x86_32/current.h @@ -45,14 +45,11 @@ static inline unsigned long get_stack_top(void) return p; } -#define schedule_tail(_p) \ +#define reset_stack_and_jump(__fn) \ __asm__ __volatile__ ( \ - "andl %%esp,%0; addl %2,%0; movl %0,%%esp; jmp *%1" \ - : : "r" (~(STACK_SIZE-1)), \ - "r" (unlikely(is_idle_task((_p))) ? \ - continue_cpu_idle_loop : \ - continue_nonidle_task), \ - "i" (STACK_SIZE-STACK_RESERVED) ) + "movl %0,%%esp; jmp "STR(__fn) \ + : : "r" (get_execution_context()) ) +#define schedule_tail(_d) ((_d)->thread.schedule_tail)(_d) #endif /* _X86_CURRENT_H */ diff --git a/xen/include/asm-x86/x86_32/uaccess.h b/xen/include/asm-x86/x86_32/uaccess.h index 650492d59e..b202a1a12b 100644 --- a/xen/include/asm-x86/x86_32/uaccess.h +++ b/xen/include/asm-x86/x86_32/uaccess.h @@ -69,27 +69,6 @@ extern struct movsl_mask { #define array_access_ok(type,addr,count,size) \ (likely(count < (~0UL/size)) && access_ok(type,addr,count*size)) -/* - * The exception table consists of pairs of addresses: the first is the - * address of an instruction that is allowed to fault, and the second is - * the address at which the program should continue. No registers are - * modified, so it is entirely up to the continuation code to figure out - * what to do. - * - * All the routines below use bits of fixup code that are out of line - * with the main instruction path. This means when everything is well, - * we don't even have to jump over them. Further, they do not intrude - * on our cache or tlb entries. - */ - -struct exception_table_entry -{ - unsigned long insn, fixup; -}; - -extern unsigned long search_exception_table(unsigned long); -extern void sort_exception_tables(void); - /** * get_user: - Get a simple variable from user space. * @x: Variable to store result. diff --git a/xen/include/asm-x86/x86_64/asm_defns.h b/xen/include/asm-x86/x86_64/asm_defns.h new file mode 100644 index 0000000000..fa0b978304 --- /dev/null +++ b/xen/include/asm-x86/x86_64/asm_defns.h @@ -0,0 +1,6 @@ +#ifndef __X86_64_ASM_DEFNS_H__ +#define __X86_64_ASM_DEFNS_H__ + +#define SAVE_ALL(_r) "" + +#endif /* __X86_64_ASM_DEFNS_H__ */ diff --git a/xen/include/asm-x86/x86_64/current.h b/xen/include/asm-x86/x86_64/current.h index 2f3a6e5665..2ee550643b 100644 --- a/xen/include/asm-x86/x86_64/current.h +++ b/xen/include/asm-x86/x86_64/current.h @@ -40,15 +40,12 @@ static inline unsigned long get_stack_top(void) return p; } -#define schedule_tail(_p) \ +#define reset_stack_and_jump(__fn) \ __asm__ __volatile__ ( \ - "andq %%rsp,%0; addq %2,%0; movq %0,%%rsp; jmp *%1" \ - : : "r" (~(STACK_SIZE-1)), \ - "r" (unlikely(is_idle_task((_p))) ? \ - continue_cpu_idle_loop : \ - continue_nonidle_task), \ - "i" (STACK_SIZE-STACK_RESERVED) ) + "movq %0,%%rsp; jmp "STR(__fn) \ + : : "r" (get_execution_context()) ) +#define schedule_tail(_d) ((_d)->thread.schedule_tail)(_d) #else diff --git a/xen/include/asm-x86/x86_64/uaccess.h b/xen/include/asm-x86/x86_64/uaccess.h index be49ff870b..f965c87d32 100644 --- a/xen/include/asm-x86/x86_64/uaccess.h +++ b/xen/include/asm-x86/x86_64/uaccess.h @@ -35,31 +35,15 @@ #define access_ok(type, addr, size) (__range_not_ok(addr,size) == 0) +#define array_access_ok(type,addr,count,size) \ + (likely(sizeof(count) <= 4) /* disallow 64-bit counts */ && \ + access_ok(type,addr,count*size)) + extern inline int verify_area(int type, const void __user * addr, unsigned long size) { return access_ok(type,addr,size) ? 0 : -EFAULT; } - -/* - * The exception table consists of pairs of addresses: the first is the - * address of an instruction that is allowed to fault, and the second is - * the address at which the program should continue. No registers are - * modified, so it is entirely up to the continuation code to figure out - * what to do. - * - * All the routines below use bits of fixup code that are out of line - * with the main instruction path. This means when everything is well, - * we don't even have to jump over them. Further, they do not intrude - * on our cache or tlb entries. - */ - -struct exception_table_entry -{ - unsigned long insn, fixup; -}; - - /* * These are the main single-value transfer routines. They automatically * use the right size if we just have the right pointer type. diff --git a/xen/include/public/arch-x86_32.h b/xen/include/public/arch-x86_32.h index dee8b783ef..b7210fc1b5 100644 --- a/xen/include/public/arch-x86_32.h +++ b/xen/include/public/arch-x86_32.h @@ -2,6 +2,8 @@ * arch-x86_32.h * * Guest OS interface to x86 32-bit Xen. + * + * Copyright (c) 2004, K A Fraser */ #ifndef __XEN_PUBLIC_ARCH_X86_32_H__ diff --git a/xen/include/public/arch-x86_64.h b/xen/include/public/arch-x86_64.h index 856b5070a8..2144b0d63b 100644 --- a/xen/include/public/arch-x86_64.h +++ b/xen/include/public/arch-x86_64.h @@ -2,6 +2,8 @@ * arch-x86_64.h * * Guest OS interface to x86 64-bit Xen. + * + * Copyright (c) 2004, K A Fraser */ #ifndef __XEN_PUBLIC_ARCH_X86_64_H__ diff --git a/xen/include/public/io/domain_controller.h b/xen/include/public/io/domain_controller.h index 5a4056cd4d..c248f21419 100644 --- a/xen/include/public/io/domain_controller.h +++ b/xen/include/public/io/domain_controller.h @@ -555,6 +555,7 @@ typedef struct { #define CMSG_SHUTDOWN_REBOOT 1 /* Clean shutdown (SHUTDOWN_reboot). */ #define CMSG_SHUTDOWN_SUSPEND 2 /* Create suspend info, then */ /* SHUTDOWN_suspend. */ +#define CMSG_SHUTDOWN_SYSRQ 3 /****************************************************************************** diff --git a/xen/include/public/trace.h b/xen/include/public/trace.h index 5e7904d52a..e4ee78b975 100644 --- a/xen/include/public/trace.h +++ b/xen/include/public/trace.h @@ -1,5 +1,7 @@ /****************************************************************************** * trace.h + * + * Mark Williamson, (C) 2004 Intel Research Cambridge */ #ifndef __XEN_PUBLIC_TRACE_H__ diff --git a/xen/include/asm-x86/domain.h b/xen/include/xen/domain.h index 7dde4efa6d..5ff5ed62ad 100644 --- a/xen/include/asm-x86/domain.h +++ b/xen/include/xen/domain.h @@ -1,6 +1,12 @@ -#ifndef __ASM_X86_DOMAIN_H__ -#define __ASM_X86_DOMAIN_H__ +#ifndef __XEN_DOMAIN_H__ +#define __XEN_DOMAIN_H__ + + + +/* + * Arch-specifics. + */ extern void arch_do_createdomain(struct domain *d); @@ -11,4 +17,4 @@ extern void free_perdomain_pt(struct domain *d); extern void domain_relinquish_memory(struct domain *d); -#endif /* __ASM_X86_DOMAIN_H__ */ +#endif /* __XEN_DOMAIN_H__ */ diff --git a/xen/include/xen/sched.h b/xen/include/xen/sched.h index c8781f0440..d7e6f0be26 100644 --- a/xen/include/xen/sched.h +++ b/xen/include/xen/sched.h @@ -214,9 +214,6 @@ void domain_init(void); int idle_cpu(int cpu); /* Is CPU 'cpu' idle right now? */ void startup_cpu_idle_loop(void); -void continue_cpu_idle_loop(void); - -void continue_nonidle_task(void); unsigned long hypercall_create_continuation( unsigned int op, unsigned int nr_args, ...); @@ -295,6 +292,6 @@ static inline void domain_unpause_by_systemcontroller(struct domain *d) #define VM_ASSIST(_d,_t) (test_bit((_t), &(_d)->vm_assist)) #include <xen/slab.h> -#include <asm/domain.h> +#include <xen/domain.h> #endif /* __SCHED_H__ */ |