[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] merge with xen-unstable.hg
# HG changeset patch # User awilliam@xxxxxxxxxxxx # Date 1172001502 25200 # Node ID d907467f08cd4b55604961f4da4224d3ad5fe9d4 # Parent 04c23c1ef8885cf37b1c17a2f406695272ba036d # Parent ecb6cd61a9cfa70be364aace1cb183bae03b04fd merge with xen-unstable.hg --- linux-2.6-xen-sparse/drivers/char/tpm/tpm.c | 1222 --------- linux-2.6-xen-sparse/include/linux/pfn.h | 9 tools/libxc/xc_linux_build.c | 1319 ---------- tools/libxc/xc_load_bin.c | 306 -- tools/libxc/xc_load_elf.c | 684 ----- xen/common/elf.c | 520 --- extras/mini-os/Makefile | 5 extras/mini-os/arch/x86/Makefile | 5 extras/mini-os/arch/x86/arch.mk | 5 extras/mini-os/minios.mk | 17 extras/mini-os/xenbus/xenbus.c | 2 linux-2.6-xen-sparse/arch/i386/kernel/Makefile | 1 linux-2.6-xen-sparse/arch/i386/kernel/head-xen.S | 4 linux-2.6-xen-sparse/arch/i386/kernel/setup-xen.c | 38 linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c | 30 linux-2.6-xen-sparse/arch/i386/mach-xen/setup.c | 2 linux-2.6-xen-sparse/arch/i386/mm/fault-xen.c | 2 linux-2.6-xen-sparse/arch/ia64/xen/util.c | 12 linux-2.6-xen-sparse/arch/x86_64/kernel/Makefile | 1 linux-2.6-xen-sparse/arch/x86_64/kernel/e820-xen.c | 11 linux-2.6-xen-sparse/arch/x86_64/kernel/early_printk-xen.c | 11 linux-2.6-xen-sparse/arch/x86_64/kernel/entry-xen.S | 4 linux-2.6-xen-sparse/arch/x86_64/kernel/head-xen.S | 7 linux-2.6-xen-sparse/arch/x86_64/kernel/mpparse-xen.c | 2 linux-2.6-xen-sparse/arch/x86_64/kernel/process-xen.c | 4 linux-2.6-xen-sparse/arch/x86_64/kernel/setup-xen.c | 15 linux-2.6-xen-sparse/arch/x86_64/mm/fault-xen.c | 3 linux-2.6-xen-sparse/arch/x86_64/mm/init-xen.c | 26 linux-2.6-xen-sparse/drivers/char/tpm/Kconfig | 2 linux-2.6-xen-sparse/drivers/char/tpm/tpm.h | 24 linux-2.6-xen-sparse/drivers/char/tpm/tpm_vtpm.c | 3 linux-2.6-xen-sparse/drivers/xen/balloon/balloon.c | 6 linux-2.6-xen-sparse/drivers/xen/blkback/interface.c | 14 linux-2.6-xen-sparse/drivers/xen/blktap/interface.c | 14 linux-2.6-xen-sparse/drivers/xen/core/gnttab.c | 251 + linux-2.6-xen-sparse/drivers/xen/core/smpboot.c | 3 linux-2.6-xen-sparse/drivers/xen/netback/interface.c | 26 linux-2.6-xen-sparse/drivers/xen/tpmback/interface.c | 14 linux-2.6-xen-sparse/drivers/xen/util.c | 31 linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_backend_client.c | 16 linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypervisor.h | 3 linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/irqflags.h | 17 linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/maddr.h | 25 linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/page.h | 53 linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/pgtable-2level.h | 7 linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/pgtable-3level.h | 27 linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/pgtable.h | 38 linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/system.h | 3 linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/irqflags.h | 17 linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/maddr.h | 15 linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/page.h | 28 linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/pgtable.h | 62 linux-2.6-xen-sparse/include/xen/driver_util.h | 4 linux-2.6-xen-sparse/include/xen/gnttab.h | 13 patches/linux-2.6.18/x86-elfnote-as-preprocessor-macro.patch | 5 tools/blktap/drivers/Makefile | 16 tools/blktap/drivers/block-aio.c | 132 - tools/blktap/drivers/block-qcow.c | 563 ++-- tools/blktap/drivers/block-ram.c | 125 tools/blktap/drivers/block-sync.c | 95 tools/blktap/drivers/block-vmdk.c | 99 tools/blktap/drivers/img2qcow.c | 28 tools/blktap/drivers/qcow2raw.c | 75 tools/blktap/drivers/tapdisk.c | 372 ++ tools/blktap/drivers/tapdisk.h | 62 tools/blktap/lib/blktaplib.h | 13 tools/blktap/lib/xs_api.c | 8 tools/check/check_zlib_lib | 4 tools/console/daemon/io.c | 8 tools/firmware/hvmloader/acpi/build.c | 81 tools/firmware/hvmloader/acpi/dsdt.asl | 8 tools/firmware/hvmloader/acpi/dsdt.c | 866 +++--- tools/firmware/rombios/32bit/Makefile | 2 tools/firmware/rombios/32bit/tcgbios/Makefile | 2 tools/ioemu/hw/tpm_tis.c | 3 tools/libfsimage/common/fsimage.c | 4 tools/libfsimage/common/fsimage.h | 2 tools/libfsimage/common/fsimage_grub.c | 4 tools/libfsimage/common/fsimage_grub.h | 2 tools/libfsimage/common/fsimage_plugin.c | 4 tools/libfsimage/common/fsimage_plugin.h | 2 tools/libfsimage/common/fsimage_priv.h | 2 tools/libfsimage/ext2fs-lib/ext2fs-lib.c | 2 tools/libfsimage/ext2fs/fsys_ext2fs.c | 2 tools/libfsimage/reiserfs/fsys_reiserfs.c | 2 tools/libfsimage/ufs/fsys_ufs.c | 2 tools/libxc/Makefile | 4 tools/libxc/xc_dom.h | 2 tools/libxc/xc_domain.c | 4 tools/libxc/xc_hvm_build.c | 9 tools/libxc/xc_linux_restore.c | 6 tools/libxc/xc_linux_save.c | 8 tools/libxc/xc_pagetab.c | 4 tools/libxc/xc_private.c | 20 tools/libxc/xg_private.h | 84 tools/pygrub/src/fsimage/fsimage.c | 14 tools/python/xen/xend/XendDomainInfo.py | 21 tools/python/xen/xend/image.py | 1 tools/security/xensec_ezpolicy | 6 tools/xcutils/readnotes.c | 138 - xen/acm/acm_simple_type_enforcement_hooks.c | 18 xen/arch/ia64/xen/domain.c | 10 xen/arch/ia64/xen/mm.c | 4 xen/arch/x86/domain_build.c | 4 xen/arch/x86/hvm/io.c | 5 xen/arch/x86/hvm/platform.c | 31 xen/arch/x86/hvm/svm/svm.c | 32 xen/arch/x86/hvm/vlapic.c | 2 xen/arch/x86/hvm/vmx/vmx.c | 18 xen/arch/x86/mm.c | 36 xen/arch/x86/mm/shadow/common.c | 177 - xen/arch/x86/mm/shadow/multi.c | 179 - xen/arch/x86/mm/shadow/private.h | 17 xen/arch/x86/mm/shadow/types.h | 1 xen/arch/x86/traps.c | 29 xen/arch/x86/x86_32/seg_fixup.c | 5 xen/common/compat/grant_table.c | 3 xen/common/grant_table.c | 502 ++- xen/common/libelf/libelf-dominfo.c | 119 xen/common/libelf/libelf-tools.c | 11 xen/include/asm-ia64/bug.h | 6 xen/include/asm-ia64/grant_table.h | 43 xen/include/asm-powerpc/bug.h | 6 xen/include/asm-powerpc/grant_table.h | 2 xen/include/asm-x86/bug.h | 13 xen/include/asm-x86/grant_table.h | 6 xen/include/asm-x86/hvm/io.h | 1 xen/include/asm-x86/processor.h | 5 xen/include/asm-x86/x86_32/bug.h | 19 xen/include/asm-x86/x86_64/bug.h | 19 xen/include/asm-x86/x86_64/page.h | 14 xen/include/public/arch-ia64.h | 2 xen/include/public/arch-powerpc.h | 2 xen/include/public/arch-x86/xen.h | 2 xen/include/public/elfnote.h | 8 xen/include/public/grant_table.h | 19 xen/include/public/hvm/save.h | 13 xen/include/public/libelf.h | 3 xen/include/xen/grant_table.h | 38 xen/include/xen/lib.h | 5 xen/include/xen/sched.h | 9 141 files changed, 3077 insertions(+), 6260 deletions(-) diff -r 04c23c1ef888 -r d907467f08cd extras/mini-os/Makefile --- a/extras/mini-os/Makefile Sun Feb 18 16:13:13 2007 -0700 +++ b/extras/mini-os/Makefile Tue Feb 20 12:58:22 2007 -0700 @@ -44,10 +44,6 @@ ARCH_LINKS = # This can be overwritten from arch specific rules. EXTRA_INC = -# Special build dependencies. -# Build all after touching this/these file(s) (see minios.mk) -SPEC_DEPENDS = minios.mk - # Include the architecture family's special makerules. # This must be before include minios.mk! include $(TARGET_ARCH_DIR)/arch.mk @@ -57,7 +53,6 @@ include minios.mk # Define some default flags for linking. LDLIBS := -LDFLAGS := LDARCHLIB := -L$(TARGET_ARCH_DIR) -l$(ARCH_LIB_NAME) LDFLAGS_FINAL := -N -T $(TARGET_ARCH_DIR)/minios-$(TARGET_ARCH).lds diff -r 04c23c1ef888 -r d907467f08cd extras/mini-os/arch/x86/Makefile --- a/extras/mini-os/arch/x86/Makefile Sun Feb 18 16:13:13 2007 -0700 +++ b/extras/mini-os/arch/x86/Makefile Tue Feb 20 12:58:22 2007 -0700 @@ -2,9 +2,6 @@ # x86 architecture specific makefiles. # It's is used for x86_32, x86_32y and x86_64 # - -# Rebuild all after touching this/these extra file(s) (see mini-os.mk) -SPEC_DEP = arch.mk # include arch.mk has to be before mini-os.mk! include arch.mk @@ -25,5 +22,5 @@ all: $(ARCH_LIB) $(AR) rv $(ARCH_LIB) $(ARCH_OBJS) clean: - rm -f $(ARCH_LIB) $(ARCH_OBJS) + rm -f $(ARCH_LIB) $(ARCH_OBJS) $(HEAD_ARCH_OBJ) diff -r 04c23c1ef888 -r d907467f08cd extras/mini-os/arch/x86/arch.mk --- a/extras/mini-os/arch/x86/arch.mk Sun Feb 18 16:13:13 2007 -0700 +++ b/extras/mini-os/arch/x86/arch.mk Tue Feb 20 12:58:22 2007 -0700 @@ -6,6 +6,7 @@ ifeq ($(TARGET_ARCH),x86_32) ifeq ($(TARGET_ARCH),x86_32) ARCH_CFLAGS := -m32 -march=i686 ARCH_LDFLAGS := -m elf_i386 +ARCH_ASFLAGS := -m32 EXTRA_INC += $(TARGET_ARCH_FAM)/$(TARGET_ARCH) EXTRA_SRC += arch/$(EXTRA_INC) endif @@ -19,10 +20,10 @@ endif ifeq ($(TARGET_ARCH),x86_64) ARCH_CFLAGS := -m64 -mno-red-zone -fpic -fno-reorder-blocks -ARCH_CFLAGS := -fno-asynchronous-unwind-tables +ARCH_CFLAGS += -fno-asynchronous-unwind-tables +ARCH_ASFLAGS := -m64 ARCH_LDFLAGS := -m elf_x86_64 EXTRA_INC += $(TARGET_ARCH_FAM)/$(TARGET_ARCH) EXTRA_SRC += arch/$(EXTRA_INC) endif - diff -r 04c23c1ef888 -r d907467f08cd extras/mini-os/minios.mk --- a/extras/mini-os/minios.mk Sun Feb 18 16:13:13 2007 -0700 +++ b/extras/mini-os/minios.mk Tue Feb 20 12:58:22 2007 -0700 @@ -11,6 +11,7 @@ DEF_CFLAGS += -D__XEN_INTERFACE_VERSION_ DEF_CFLAGS += -D__XEN_INTERFACE_VERSION__=$(XEN_INTERFACE_VERSION) DEF_ASFLAGS = -D__ASSEMBLY__ +DEF_LDFLAGS = ifeq ($(debug),y) DEF_CFLAGS += -g @@ -23,21 +24,27 @@ endif # ARCH_... flags may be defined in arch/$(TARGET_ARCH_FAM/rules.mk CFLAGS := $(DEF_CFLAGS) $(ARCH_CFLAGS) ASFLAGS := $(DEF_ASFLAGS) $(ARCH_ASFLAGS) +LDFLAGS := $(DEF_LDFLAGS) $(ARCH_LDFLAGS) # The path pointing to the architecture specific header files. -ARCH_SPEC_INC := $(MINI-OS_ROOT)/include/$(TARGET_ARCH_FAM) +ARCH_INC := $(MINI-OS_ROOT)/include/$(TARGET_ARCH_FAM) + +# Special build dependencies. +# Rebuild all after touching this/these file(s) +EXTRA_DEPS = $(MINI-OS_ROOT)/minios.mk \ + $(MINI-OS_ROOT)/$(TARGET_ARCH_DIR)/arch.mk # Find all header files for checking dependencies. HDRS := $(wildcard $(MINI-OS_ROOT)/include/*.h) HDRS += $(wildcard $(MINI-OS_ROOT)/include/xen/*.h) -HDRS += $(wildcard $(ARCH_SPEC_INC)/*.h) +HDRS += $(wildcard $(ARCH_INC)/*.h) # For special wanted header directories. extra_heads := $(foreach dir,$(EXTRA_INC),$(wildcard $(dir)/*.h)) HDRS += $(extra_heads) # Add the special header directories to the include paths. extra_incl := $(foreach dir,$(EXTRA_INC),-I$(MINI-OS_ROOT)/include/$(dir)) -override CPPFLAGS := -I$(MINI-OS_ROOT)/include $(CPPFLAGS) -I$(ARCH_SPEC_INC) $(extra_incl) +override CPPFLAGS := -I$(MINI-OS_ROOT)/include $(CPPFLAGS) -I$(ARCH_INC) $(extra_incl) # The name of the architecture specific library. # This is on x86_32: libx86_32.a @@ -51,10 +58,10 @@ HEAD_OBJ := $(TARGET_ARCH_DIR)/$(HEAD_AR HEAD_OBJ := $(TARGET_ARCH_DIR)/$(HEAD_ARCH_OBJ) -%.o: %.c $(HDRS) Makefile $(SPEC_DEPENDS) +%.o: %.c $(HDRS) Makefile $(EXTRA_DEPS) $(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $@ -%.o: %.S $(HDRS) Makefile $(SPEC_DEPENDS) +%.o: %.S $(HDRS) Makefile $(EXTRA_DEPS) $(CC) $(ASFLAGS) $(CPPFLAGS) -c $< -o $@ diff -r 04c23c1ef888 -r d907467f08cd extras/mini-os/xenbus/xenbus.c --- a/extras/mini-os/xenbus/xenbus.c Sun Feb 18 16:13:13 2007 -0700 +++ b/extras/mini-os/xenbus/xenbus.c Tue Feb 20 12:58:22 2007 -0700 @@ -210,7 +210,7 @@ static int allocate_xenbus_id(void) } nr_live_reqs++; req_info[o_probe].in_use = 1; - probe = o_probe + 1; + probe = (o_probe + 1) % NR_REQS; spin_unlock(&req_lock); init_waitqueue_head(&req_info[o_probe].waitq); diff -r 04c23c1ef888 -r d907467f08cd linux-2.6-xen-sparse/arch/i386/kernel/Makefile --- a/linux-2.6-xen-sparse/arch/i386/kernel/Makefile Sun Feb 18 16:13:13 2007 -0700 +++ b/linux-2.6-xen-sparse/arch/i386/kernel/Makefile Tue Feb 20 12:58:22 2007 -0700 @@ -98,4 +98,5 @@ obj-y := $(call filterxen, $(obj-y), $(n obj-y := $(call filterxen, $(obj-y), $(n-obj-xen)) obj-y := $(call cherrypickxen, $(obj-y)) extra-y := $(call cherrypickxen, $(extra-y)) +%/head-xen.o %/head-xen.s: EXTRA_AFLAGS := endif diff -r 04c23c1ef888 -r d907467f08cd linux-2.6-xen-sparse/arch/i386/kernel/head-xen.S --- a/linux-2.6-xen-sparse/arch/i386/kernel/head-xen.S Sun Feb 18 16:13:13 2007 -0700 +++ b/linux-2.6-xen-sparse/arch/i386/kernel/head-xen.S Tue Feb 20 12:58:22 2007 -0700 @@ -11,6 +11,8 @@ #include <asm/asm-offsets.h> #include <xen/interface/xen.h> #include <xen/interface/elfnote.h> + +#define _PAGE_PRESENT 0x1 /* * References to members of the new_cpu_data structure. @@ -198,7 +200,9 @@ ENTRY(cpu_gdt_table) ELFNOTE(Xen, XEN_ELFNOTE_FEATURES, .asciz, "writable_page_tables|writable_descriptor_tables|auto_translated_physmap|pae_pgdir_above_4gb|supervisor_mode_kernel") #ifdef CONFIG_X86_PAE ELFNOTE(Xen, XEN_ELFNOTE_PAE_MODE, .asciz, "yes") + ELFNOTE(Xen, XEN_ELFNOTE_L1_MFN_VALID, .quad, _PAGE_PRESENT,_PAGE_PRESENT) #else ELFNOTE(Xen, XEN_ELFNOTE_PAE_MODE, .asciz, "no") + ELFNOTE(Xen, XEN_ELFNOTE_L1_MFN_VALID, .long, _PAGE_PRESENT,_PAGE_PRESENT) #endif ELFNOTE(Xen, XEN_ELFNOTE_LOADER, .asciz, "generic") diff -r 04c23c1ef888 -r d907467f08cd linux-2.6-xen-sparse/arch/i386/kernel/setup-xen.c --- a/linux-2.6-xen-sparse/arch/i386/kernel/setup-xen.c Sun Feb 18 16:13:13 2007 -0700 +++ b/linux-2.6-xen-sparse/arch/i386/kernel/setup-xen.c Tue Feb 20 12:58:22 2007 -0700 @@ -1034,8 +1034,16 @@ e820_all_mapped(unsigned long s, unsigne u64 start = s; u64 end = e; int i; + +#ifndef CONFIG_XEN for (i = 0; i < e820.nr_map; i++) { struct e820entry *ei = &e820.map[i]; +#else + if (!is_initial_xendomain()) + return 0; + for (i = 0; i < machine_e820.nr_map; ++i) { + const struct e820entry *ei = &machine_e820.map[i]; +#endif if (type && ei->type != type) continue; /* is the region (part) in overlap with the current region ?*/ @@ -1505,9 +1513,6 @@ e820_setup_gap(struct e820entry *e820, i */ static int __init request_standard_resources(void) { -#ifdef CONFIG_XEN - struct xen_memory_map memmap; -#endif int i; /* Nothing to do if not running in dom0. */ @@ -1516,13 +1521,6 @@ static int __init request_standard_resou printk("Setting up standard PCI resources\n"); #ifdef CONFIG_XEN - memmap.nr_entries = E820MAX; - set_xen_guest_handle(memmap.buffer, machine_e820.map); - - if (HYPERVISOR_memory_op(XENMEM_machine_memory_map, &memmap)) - BUG(); - machine_e820.nr_map = memmap.nr_entries; - legacy_init_iomem_resources(machine_e820.map, machine_e820.nr_map, &code_resource, &data_resource); #else @@ -1546,12 +1544,22 @@ subsys_initcall(request_standard_resourc static void __init register_memory(void) { - #ifdef CONFIG_XEN - e820_setup_gap(machine_e820.map, machine_e820.nr_map); -#else - e820_setup_gap(e820.map, e820.nr_map); -#endif + if (is_initial_xendomain()) { + struct xen_memory_map memmap; + + memmap.nr_entries = E820MAX; + set_xen_guest_handle(memmap.buffer, machine_e820.map); + + if (HYPERVISOR_memory_op(XENMEM_machine_memory_map, &memmap)) + BUG(); + + machine_e820.nr_map = memmap.nr_entries; + e820_setup_gap(machine_e820.map, machine_e820.nr_map); + } + else +#endif + e820_setup_gap(e820.map, e820.nr_map); } #ifdef CONFIG_MCA diff -r 04c23c1ef888 -r d907467f08cd linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c --- a/linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c Sun Feb 18 16:13:13 2007 -0700 +++ b/linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c Tue Feb 20 12:58:22 2007 -0700 @@ -222,8 +222,7 @@ void init_cpu_khz(void) void init_cpu_khz(void) { u64 __cpu_khz = 1000000ULL << 32; - struct vcpu_time_info *info; - info = &HYPERVISOR_shared_info->vcpu_info[0].time; + struct vcpu_time_info *info = &vcpu_info(0)->time; do_div(__cpu_khz, info->tsc_to_system_mul); if (info->tsc_shift < 0) cpu_khz = __cpu_khz << -info->tsc_shift; @@ -293,14 +292,13 @@ static void update_wallclock(void) * Reads a consistent set of time-base values from Xen, into a shadow data * area. */ -static void get_time_values_from_xen(void) -{ - shared_info_t *s = HYPERVISOR_shared_info; +static void get_time_values_from_xen(int cpu) +{ struct vcpu_time_info *src; struct shadow_time_info *dst; - src = &s->vcpu_info[smp_processor_id()].time; - dst = &per_cpu(shadow_time, smp_processor_id()); + src = &vcpu_info(cpu)->time; + dst = &per_cpu(shadow_time, cpu); do { dst->version = src->version; @@ -320,7 +318,7 @@ static inline int time_values_up_to_date struct vcpu_time_info *src; struct shadow_time_info *dst; - src = &HYPERVISOR_shared_info->vcpu_info[cpu].time; + src = &vcpu_info(cpu)->time; dst = &per_cpu(shadow_time, cpu); rmb(); @@ -412,7 +410,7 @@ void do_gettimeofday(struct timeval *tv) * overflowed). Detect that and recalculate * with fresh values. */ - get_time_values_from_xen(); + get_time_values_from_xen(cpu); continue; } } while (read_seqretry(&xtime_lock, seq) || @@ -456,7 +454,7 @@ int do_settimeofday(struct timespec *tv) nsec = tv->tv_nsec - get_nsec_offset(shadow); if (time_values_up_to_date(cpu)) break; - get_time_values_from_xen(); + get_time_values_from_xen(cpu); } sec = tv->tv_sec; __normalize_time(&sec, &nsec); @@ -551,7 +549,7 @@ unsigned long long monotonic_clock(void) barrier(); time = shadow->system_timestamp + get_nsec_offset(shadow); if (!time_values_up_to_date(cpu)) - get_time_values_from_xen(); + get_time_values_from_xen(cpu); barrier(); } while (local_time_version != shadow->version); @@ -621,7 +619,7 @@ irqreturn_t timer_interrupt(int irq, voi write_seqlock(&xtime_lock); do { - get_time_values_from_xen(); + get_time_values_from_xen(cpu); /* Obtain a consistent snapshot of elapsed wallclock cycles. */ delta = delta_cpu = @@ -708,7 +706,7 @@ irqreturn_t timer_interrupt(int irq, voi if (delta_cpu > 0) { do_div(delta_cpu, NS_PER_TICK); per_cpu(processed_system_time, cpu) += delta_cpu * NS_PER_TICK; - if (user_mode(regs)) + if (user_mode_vm(regs)) account_user_time(current, (cputime_t)delta_cpu); else account_system_time(current, HARDIRQ_OFFSET, @@ -722,7 +720,7 @@ irqreturn_t timer_interrupt(int irq, voi /* Local timer processing (see update_process_times()). */ run_local_timers(); if (rcu_pending(cpu)) - rcu_check_callbacks(cpu, user_mode(regs)); + rcu_check_callbacks(cpu, user_mode_vm(regs)); scheduler_tick(); run_posix_cpu_timers(current); profile_tick(CPU_PROFILING, regs); @@ -921,7 +919,7 @@ void __init time_init(void) return; } #endif - get_time_values_from_xen(); + get_time_values_from_xen(0); processed_system_time = per_cpu(shadow_time, 0).system_timestamp; per_cpu(processed_system_time, 0) = processed_system_time; @@ -1029,7 +1027,7 @@ void time_resume(void) { init_cpu_khz(); - get_time_values_from_xen(); + get_time_values_from_xen(0); processed_system_time = per_cpu(shadow_time, 0).system_timestamp; per_cpu(processed_system_time, 0) = processed_system_time; diff -r 04c23c1ef888 -r d907467f08cd linux-2.6-xen-sparse/arch/i386/mach-xen/setup.c --- a/linux-2.6-xen-sparse/arch/i386/mach-xen/setup.c Sun Feb 18 16:13:13 2007 -0700 +++ b/linux-2.6-xen-sparse/arch/i386/mach-xen/setup.c Tue Feb 20 12:58:22 2007 -0700 @@ -67,7 +67,7 @@ char * __init machine_specific_memory_se if ( rc == -ENOSYS ) { memmap.nr_entries = 1; map[0].addr = 0ULL; - map[0].size = PFN_PHYS(xen_start_info->nr_pages); + map[0].size = PFN_PHYS((unsigned long long)xen_start_info->nr_pages); /* 8MB slack (to balance backend allocations). */ map[0].size += 8ULL << 20; map[0].type = E820_RAM; diff -r 04c23c1ef888 -r d907467f08cd linux-2.6-xen-sparse/arch/i386/mm/fault-xen.c --- a/linux-2.6-xen-sparse/arch/i386/mm/fault-xen.c Sun Feb 18 16:13:13 2007 -0700 +++ b/linux-2.6-xen-sparse/arch/i386/mm/fault-xen.c Tue Feb 20 12:58:22 2007 -0700 @@ -731,7 +731,7 @@ do_sigbus: force_sig_info_fault(SIGBUS, BUS_ADRERR, address, tsk); } -#ifndef CONFIG_X86_PAE +#if !HAVE_SHARED_KERNEL_PMD void vmalloc_sync_all(void) { /* diff -r 04c23c1ef888 -r d907467f08cd linux-2.6-xen-sparse/arch/ia64/xen/util.c --- a/linux-2.6-xen-sparse/arch/ia64/xen/util.c Sun Feb 18 16:13:13 2007 -0700 +++ b/linux-2.6-xen-sparse/arch/ia64/xen/util.c Tue Feb 20 12:58:22 2007 -0700 @@ -95,18 +95,6 @@ void free_vm_area(struct vm_struct *area } EXPORT_SYMBOL_GPL(free_vm_area); -void lock_vm_area(struct vm_struct *area) -{ - // nothing -} -EXPORT_SYMBOL_GPL(lock_vm_area); - -void unlock_vm_area(struct vm_struct *area) -{ - // nothing -} -EXPORT_SYMBOL_GPL(unlock_vm_area); - /* * Local variables: * c-file-style: "linux" diff -r 04c23c1ef888 -r d907467f08cd linux-2.6-xen-sparse/arch/x86_64/kernel/Makefile --- a/linux-2.6-xen-sparse/arch/x86_64/kernel/Makefile Sun Feb 18 16:13:13 2007 -0700 +++ b/linux-2.6-xen-sparse/arch/x86_64/kernel/Makefile Tue Feb 20 12:58:22 2007 -0700 @@ -72,4 +72,5 @@ obj-y := $(call filterxen, $(obj-y), $(n obj-y := $(call filterxen, $(obj-y), $(n-obj-xen)) obj-y := $(call cherrypickxen, $(obj-y)) extra-y := $(call cherrypickxen, $(extra-y)) +%/head-xen.o %/head-xen.s: EXTRA_AFLAGS := endif diff -r 04c23c1ef888 -r d907467f08cd linux-2.6-xen-sparse/arch/x86_64/kernel/e820-xen.c --- a/linux-2.6-xen-sparse/arch/x86_64/kernel/e820-xen.c Sun Feb 18 16:13:13 2007 -0700 +++ b/linux-2.6-xen-sparse/arch/x86_64/kernel/e820-xen.c Tue Feb 20 12:58:22 2007 -0700 @@ -127,8 +127,19 @@ int __init e820_all_mapped(unsigned long int __init e820_all_mapped(unsigned long start, unsigned long end, unsigned type) { int i; + +#ifndef CONFIG_XEN for (i = 0; i < e820.nr_map; i++) { struct e820entry *ei = &e820.map[i]; +#else + extern struct e820map machine_e820; + + if (!is_initial_xendomain()) + return 0; + for (i = 0; i < machine_e820.nr_map; i++) { + const struct e820entry *ei = &machine_e820.map[i]; +#endif + if (type && ei->type != type) continue; /* is the region (part) in overlap with the current region ?*/ diff -r 04c23c1ef888 -r d907467f08cd linux-2.6-xen-sparse/arch/x86_64/kernel/early_printk-xen.c --- a/linux-2.6-xen-sparse/arch/x86_64/kernel/early_printk-xen.c Sun Feb 18 16:13:13 2007 -0700 +++ b/linux-2.6-xen-sparse/arch/x86_64/kernel/early_printk-xen.c Tue Feb 20 12:58:22 2007 -0700 @@ -18,9 +18,8 @@ #define VGABASE ((void __iomem *)0xffffffff800b8000UL) #endif +#ifndef CONFIG_XEN static int max_ypos = 25, max_xpos = 80; - -#ifndef CONFIG_XEN static int current_ypos = 25, current_xpos = 0; static void early_vga_write(struct console *con, const char *str, unsigned n) @@ -154,10 +153,6 @@ static __init void early_serial_init(cha #else /* CONFIG_XEN */ -#undef SCREEN_INFO -#define SCREEN_INFO screen_info -extern struct screen_info screen_info; - static void early_serial_write(struct console *con, const char *s, unsigned count) { @@ -273,11 +268,13 @@ int __init setup_early_printk(char *opt) early_serial_init(buf); early_console = &early_serial_console; } else if (!strncmp(buf, "vga", 3) +#ifndef CONFIG_XEN && SCREEN_INFO.orig_video_isVGA == 1) { max_xpos = SCREEN_INFO.orig_video_cols; max_ypos = SCREEN_INFO.orig_video_lines; -#ifndef CONFIG_XEN current_ypos = SCREEN_INFO.orig_y; +#else + || !strncmp(buf, "xen", 3)) { #endif early_console = &early_vga_console; } else if (!strncmp(buf, "simnow", 6)) { diff -r 04c23c1ef888 -r d907467f08cd linux-2.6-xen-sparse/arch/x86_64/kernel/entry-xen.S --- a/linux-2.6-xen-sparse/arch/x86_64/kernel/entry-xen.S Sun Feb 18 16:13:13 2007 -0700 +++ b/linux-2.6-xen-sparse/arch/x86_64/kernel/entry-xen.S Tue Feb 20 12:58:22 2007 -0700 @@ -32,9 +32,6 @@ */ #define ASSEMBLY 1 -#ifdef CONFIG_DEBUG_INFO -#undef CONFIG_DEBUG_INFO -#endif #include <linux/linkage.h> #include <asm/segment.h> #include <asm/smp.h> @@ -537,6 +534,7 @@ END(stub_rt_sigreturn) */ retint_check: + CFI_DEFAULT_STACK movl threadinfo_flags(%rcx),%edx andl %edi,%edx CFI_REMEMBER_STATE diff -r 04c23c1ef888 -r d907467f08cd linux-2.6-xen-sparse/arch/x86_64/kernel/head-xen.S --- a/linux-2.6-xen-sparse/arch/x86_64/kernel/head-xen.S Sun Feb 18 16:13:13 2007 -0700 +++ b/linux-2.6-xen-sparse/arch/x86_64/kernel/head-xen.S Tue Feb 20 12:58:22 2007 -0700 @@ -25,7 +25,9 @@ #include <xen/interface/elfnote.h> - .text +#define _PAGE_PRESENT 0x1 + + .section .bootstrap.text, "ax", @progbits .code64 #define VIRT_ENTRY_OFFSET 0x0 .org VIRT_ENTRY_OFFSET @@ -49,7 +51,7 @@ ENTRY(_stext) #define NEXT_PAGE(name) \ $page = $page + 1; \ .org $page * 0x1000; \ - phys_/**/name = $page * 0x1000 + __PHYSICAL_START; \ + phys_##name = $page * 0x1000 + __PHYSICAL_START; \ ENTRY(name) NEXT_PAGE(init_level4_pgt) @@ -181,5 +183,6 @@ ENTRY(empty_zero_page) #endif /* !CONFIG_XEN_COMPAT_030002 */ ELFNOTE(Xen, XEN_ELFNOTE_ENTRY, .quad, startup_64) ELFNOTE(Xen, XEN_ELFNOTE_HYPERCALL_PAGE, .quad, hypercall_page) + ELFNOTE(Xen, XEN_ELFNOTE_L1_MFN_VALID, .quad, _PAGE_PRESENT,_PAGE_PRESENT) ELFNOTE(Xen, XEN_ELFNOTE_FEATURES, .asciz, "writable_page_tables|writable_descriptor_tables|auto_translated_physmap|pae_pgdir_above_4gb|supervisor_mode_kernel") ELFNOTE(Xen, XEN_ELFNOTE_LOADER, .asciz, "generic") diff -r 04c23c1ef888 -r d907467f08cd linux-2.6-xen-sparse/arch/x86_64/kernel/mpparse-xen.c --- a/linux-2.6-xen-sparse/arch/x86_64/kernel/mpparse-xen.c Sun Feb 18 16:13:13 2007 -0700 +++ b/linux-2.6-xen-sparse/arch/x86_64/kernel/mpparse-xen.c Tue Feb 20 12:58:22 2007 -0700 @@ -170,7 +170,7 @@ static void __cpuinit MP_processor_info cpu_set(cpu, cpu_present_map); } #else -void __init MP_processor_info (struct mpc_config_processor *m) +static void __cpuinit MP_processor_info (struct mpc_config_processor *m) { num_processors++; } diff -r 04c23c1ef888 -r d907467f08cd linux-2.6-xen-sparse/arch/x86_64/kernel/process-xen.c --- a/linux-2.6-xen-sparse/arch/x86_64/kernel/process-xen.c Sun Feb 18 16:13:13 2007 -0700 +++ b/linux-2.6-xen-sparse/arch/x86_64/kernel/process-xen.c Tue Feb 20 12:58:22 2007 -0700 @@ -499,8 +499,6 @@ __switch_to(struct task_struct *prev_p, * This is basically '__unlazy_fpu', except that we queue a * multicall to indicate FPU task switch, rather than * synchronously trapping to Xen. - * This must be here to ensure both math_state_restore() and - * kernel_fpu_begin() work consistently. * The AMD workaround requires it to be after DS reload, or * after DS has been cleared, which we do in __prepare_arch_switch. */ @@ -579,7 +577,7 @@ __switch_to(struct task_struct *prev_p, HYPERVISOR_set_segment_base(SEGBASE_GS_USER, next->gs); /* - * Switch the PDA and FPU contexts. + * Switch the PDA context. */ prev->userrsp = read_pda(oldrsp); write_pda(oldrsp, next->userrsp); diff -r 04c23c1ef888 -r d907467f08cd linux-2.6-xen-sparse/arch/x86_64/kernel/setup-xen.c --- a/linux-2.6-xen-sparse/arch/x86_64/kernel/setup-xen.c Sun Feb 18 16:13:13 2007 -0700 +++ b/linux-2.6-xen-sparse/arch/x86_64/kernel/setup-xen.c Tue Feb 20 12:58:22 2007 -0700 @@ -90,9 +90,6 @@ extern char hypercall_page[PAGE_SIZE]; extern char hypercall_page[PAGE_SIZE]; EXPORT_SYMBOL(hypercall_page); -/* Allows setting of maximum possible memory size */ -unsigned long xen_override_max_pfn; - static int xen_panic_event(struct notifier_block *, unsigned long, void *); static struct notifier_block xen_panic_block = { xen_panic_event, NULL, 0 /* try to go last */ @@ -580,13 +577,13 @@ static void discover_ebda(void) if (ebda_size > 64*1024) ebda_size = 64*1024; } +#else +#define discover_ebda() ((void)0) #endif void __init setup_arch(char **cmdline_p) { #ifdef CONFIG_XEN - struct xen_memory_map memmap; - /* Register a call for panic conditions. */ atomic_notifier_chain_register(&panic_notifier_list, &xen_panic_block); @@ -675,9 +672,7 @@ void __init setup_arch(char **cmdline_p) check_efer(); -#ifndef CONFIG_XEN discover_ebda(); -#endif init_memory_mapping(0, (end_pfn_map << PAGE_SHIFT)); @@ -719,7 +714,6 @@ void __init setup_arch(char **cmdline_p) /* reserve ebda region */ if (ebda_addr) reserve_bootmem_generic(ebda_addr, ebda_size); -#endif #ifdef CONFIG_SMP /* @@ -731,6 +725,7 @@ void __init setup_arch(char **cmdline_p) /* Reserve SMP trampoline */ reserve_bootmem_generic(SMP_TRAMPOLINE_BASE, PAGE_SIZE); +#endif #endif #ifdef CONFIG_ACPI_SLEEP @@ -895,6 +890,8 @@ void __init setup_arch(char **cmdline_p) probe_roms(); #ifdef CONFIG_XEN if (is_initial_xendomain()) { + struct xen_memory_map memmap; + memmap.nr_entries = E820MAX; set_xen_guest_handle(memmap.buffer, machine_e820.map); @@ -1378,9 +1375,7 @@ void __cpuinit identify_cpu(struct cpuin c->x86_capability[2] = cpuid_edx(0x80860001); } -#ifdef CONFIG_X86_XEN_GENAPIC c->apicid = phys_pkg_id(0); -#endif /* * Vendor-specific initialization. In this section we diff -r 04c23c1ef888 -r d907467f08cd linux-2.6-xen-sparse/arch/x86_64/mm/fault-xen.c --- a/linux-2.6-xen-sparse/arch/x86_64/mm/fault-xen.c Sun Feb 18 16:13:13 2007 -0700 +++ b/linux-2.6-xen-sparse/arch/x86_64/mm/fault-xen.c Tue Feb 20 12:58:22 2007 -0700 @@ -411,8 +411,7 @@ asmlinkage void __kprobes do_page_fault( prefetchw(&mm->mmap_sem); /* get the address */ - address = HYPERVISOR_shared_info->vcpu_info[ - smp_processor_id()].arch.cr2; + address = current_vcpu_info()->arch.cr2; info.si_code = SEGV_MAPERR; diff -r 04c23c1ef888 -r d907467f08cd linux-2.6-xen-sparse/arch/x86_64/mm/init-xen.c --- a/linux-2.6-xen-sparse/arch/x86_64/mm/init-xen.c Sun Feb 18 16:13:13 2007 -0700 +++ b/linux-2.6-xen-sparse/arch/x86_64/mm/init-xen.c Tue Feb 20 12:58:22 2007 -0700 @@ -77,7 +77,7 @@ extern unsigned long start_pfn; (((mfn_to_pfn((addr) >> PAGE_SHIFT)) << PAGE_SHIFT) + \ __START_KERNEL_map))) -static void early_make_page_readonly(void *va, unsigned int feature) +static void __meminit early_make_page_readonly(void *va, unsigned int feature) { unsigned long addr, _va = (unsigned long)va; pte_t pte, *ptep; @@ -279,8 +279,8 @@ static __init void set_pte_phys(unsigned __flush_tlb_one(vaddr); } -static void set_pte_phys_ma(unsigned long vaddr, - unsigned long phys, pgprot_t prot) +static __init void set_pte_phys_ma(unsigned long vaddr, + unsigned long phys, pgprot_t prot) { pgd_t *pgd; pud_t *pud; @@ -361,9 +361,10 @@ __set_fixmap (enum fixed_addresses idx, } /* - * At this point it only supports vsyscall area. + * This only supports vsyscall area. */ -void __set_fixmap_user (enum fixed_addresses idx, unsigned long phys, pgprot_t prot) +void __init +__set_fixmap_user (enum fixed_addresses idx, unsigned long phys, pgprot_t prot) { unsigned long address = __fix_to_virt(idx); @@ -376,15 +377,6 @@ void __set_fixmap_user (enum fixed_addre } unsigned long __initdata table_start, table_end; - -unsigned long get_machine_pfn(unsigned long addr) -{ - pud_t* pud = pud_offset_k(NULL, addr); - pmd_t* pmd = pmd_offset(pud, addr); - pte_t *pte = pte_offset_kernel(pmd, addr); - - return pte_mfn(*pte); -} static __meminit void *alloc_static_page(unsigned long *phys) { @@ -531,10 +523,6 @@ void __init xen_init_pt(void) { unsigned long addr, *page; - memset((void *)init_level4_pgt, 0, PAGE_SIZE); - memset((void *)level3_kernel_pgt, 0, PAGE_SIZE); - memset((void *)level2_kernel_pgt, 0, PAGE_SIZE); - /* Find the initial pte page that was built for us. */ page = (unsigned long *)xen_start_info->pt_base; addr = page[pgd_index(__START_KERNEL_map)]; @@ -595,7 +583,7 @@ void __init xen_init_pt(void) mk_kernel_pgd(__pa_symbol(level3_user_pgt))); } -void __init extend_init_mapping(unsigned long tables_space) +static void __init extend_init_mapping(unsigned long tables_space) { unsigned long va = __START_KERNEL_map; unsigned long phys, addr, *pte_page; diff -r 04c23c1ef888 -r d907467f08cd linux-2.6-xen-sparse/drivers/char/tpm/Kconfig --- a/linux-2.6-xen-sparse/drivers/char/tpm/Kconfig Sun Feb 18 16:13:13 2007 -0700 +++ b/linux-2.6-xen-sparse/drivers/char/tpm/Kconfig Tue Feb 20 12:58:22 2007 -0700 @@ -22,7 +22,7 @@ config TCG_TPM config TCG_TIS tristate "TPM Interface Specification 1.2 Interface" - depends on TCG_TPM + depends on TCG_TPM && PNPACPI ---help--- If you have a TPM security chip that is compliant with the TCG TIS 1.2 TPM specification say Yes and it will be accessible diff -r 04c23c1ef888 -r d907467f08cd linux-2.6-xen-sparse/drivers/char/tpm/tpm.c --- a/linux-2.6-xen-sparse/drivers/char/tpm/tpm.c Sun Feb 18 16:13:13 2007 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1222 +0,0 @@ -/* - * Copyright (C) 2004 IBM Corporation - * - * Authors: - * Leendert van Doorn <leendert@xxxxxxxxxxxxxx> - * Dave Safford <safford@xxxxxxxxxxxxxx> - * Reiner Sailer <sailer@xxxxxxxxxxxxxx> - * Kylene Hall <kjhall@xxxxxxxxxx> - * - * Maintained by: <tpmdd_devel@xxxxxxxxxxxxxxxxxxxxx> - * - * Device driver for TCG/TCPA TPM (trusted platform module). - * Specifications at www.trustedcomputinggroup.org - * - * 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, version 2 of the - * License. - * - * Note, the TPM chip is not interrupt driven (only polling) - * and can have very long timeouts (minutes!). Hence the unusual - * calls to msleep. - * - */ - -#include <linux/sched.h> -#include <linux/poll.h> -#include <linux/spinlock.h> -#include "tpm.h" - -enum tpm_const { - TPM_MINOR = 224, /* officially assigned */ -#ifndef CONFIG_XEN - TPM_BUFSIZE = 2048, -#endif - TPM_NUM_DEVICES = 256, -}; - -enum tpm_duration { - TPM_SHORT = 0, - TPM_MEDIUM = 1, - TPM_LONG = 2, - TPM_UNDEFINED, -}; - -#define TPM_MAX_ORDINAL 243 -#define TPM_MAX_PROTECTED_ORDINAL 12 -#define TPM_PROTECTED_ORDINAL_MASK 0xFF - -static LIST_HEAD(tpm_chip_list); -static DEFINE_SPINLOCK(driver_lock); -static DECLARE_BITMAP(dev_mask, TPM_NUM_DEVICES); - -/* - * Array with one entry per ordinal defining the maximum amount - * of time the chip could take to return the result. The ordinal - * designation of short, medium or long is defined in a table in - * TCG Specification TPM Main Part 2 TPM Structures Section 17. The - * values of the SHORT, MEDIUM, and LONG durations are retrieved - * from the chip during initialization with a call to tpm_get_timeouts. - */ -static const u8 tpm_protected_ordinal_duration[TPM_MAX_PROTECTED_ORDINAL] = { - TPM_UNDEFINED, /* 0 */ - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, /* 5 */ - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_SHORT, /* 10 */ - TPM_SHORT, -}; - -static const u8 tpm_ordinal_duration[TPM_MAX_ORDINAL] = { - TPM_UNDEFINED, /* 0 */ - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, /* 5 */ - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_SHORT, /* 10 */ - TPM_SHORT, - TPM_MEDIUM, - TPM_LONG, - TPM_LONG, - TPM_MEDIUM, /* 15 */ - TPM_SHORT, - TPM_SHORT, - TPM_MEDIUM, - TPM_LONG, - TPM_SHORT, /* 20 */ - TPM_SHORT, - TPM_MEDIUM, - TPM_MEDIUM, - TPM_MEDIUM, - TPM_SHORT, /* 25 */ - TPM_SHORT, - TPM_MEDIUM, - TPM_SHORT, - TPM_SHORT, - TPM_MEDIUM, /* 30 */ - TPM_LONG, - TPM_MEDIUM, - TPM_SHORT, - TPM_SHORT, - TPM_SHORT, /* 35 */ - TPM_MEDIUM, - TPM_MEDIUM, - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_MEDIUM, /* 40 */ - TPM_LONG, - TPM_MEDIUM, - TPM_SHORT, - TPM_SHORT, - TPM_SHORT, /* 45 */ - TPM_SHORT, - TPM_SHORT, - TPM_SHORT, - TPM_LONG, - TPM_MEDIUM, /* 50 */ - TPM_MEDIUM, - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, /* 55 */ - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_MEDIUM, /* 60 */ - TPM_MEDIUM, - TPM_MEDIUM, - TPM_SHORT, - TPM_SHORT, - TPM_MEDIUM, /* 65 */ - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_SHORT, /* 70 */ - TPM_SHORT, - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, /* 75 */ - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_LONG, /* 80 */ - TPM_UNDEFINED, - TPM_MEDIUM, - TPM_LONG, - TPM_SHORT, - TPM_UNDEFINED, /* 85 */ - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_SHORT, /* 90 */ - TPM_SHORT, - TPM_SHORT, - TPM_SHORT, - TPM_SHORT, - TPM_UNDEFINED, /* 95 */ - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_MEDIUM, /* 100 */ - TPM_SHORT, - TPM_SHORT, - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, /* 105 */ - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_SHORT, /* 110 */ - TPM_SHORT, - TPM_SHORT, - TPM_SHORT, - TPM_SHORT, - TPM_SHORT, /* 115 */ - TPM_SHORT, - TPM_SHORT, - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_LONG, /* 120 */ - TPM_LONG, - TPM_MEDIUM, - TPM_UNDEFINED, - TPM_SHORT, - TPM_SHORT, /* 125 */ - TPM_SHORT, - TPM_LONG, - TPM_SHORT, - TPM_SHORT, - TPM_SHORT, /* 130 */ - TPM_MEDIUM, - TPM_UNDEFINED, - TPM_SHORT, - TPM_MEDIUM, - TPM_UNDEFINED, /* 135 */ - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_SHORT, /* 140 */ - TPM_SHORT, - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, /* 145 */ - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_SHORT, /* 150 */ - TPM_MEDIUM, - TPM_MEDIUM, - TPM_SHORT, - TPM_SHORT, - TPM_UNDEFINED, /* 155 */ - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_SHORT, /* 160 */ - TPM_SHORT, - TPM_SHORT, - TPM_SHORT, - TPM_UNDEFINED, - TPM_UNDEFINED, /* 165 */ - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_LONG, /* 170 */ - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, /* 175 */ - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_MEDIUM, /* 180 */ - TPM_SHORT, - TPM_MEDIUM, - TPM_MEDIUM, - TPM_MEDIUM, - TPM_MEDIUM, /* 185 */ - TPM_SHORT, - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, /* 190 */ - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, /* 195 */ - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_SHORT, /* 200 */ - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_SHORT, - TPM_SHORT, /* 205 */ - TPM_SHORT, - TPM_SHORT, - TPM_SHORT, - TPM_SHORT, - TPM_MEDIUM, /* 210 */ - TPM_UNDEFINED, - TPM_MEDIUM, - TPM_MEDIUM, - TPM_MEDIUM, - TPM_UNDEFINED, /* 215 */ - TPM_MEDIUM, - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_SHORT, - TPM_SHORT, /* 220 */ - TPM_SHORT, - TPM_SHORT, - TPM_SHORT, - TPM_SHORT, - TPM_UNDEFINED, /* 225 */ - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_SHORT, /* 230 */ - TPM_LONG, - TPM_MEDIUM, - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, /* 235 */ - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_UNDEFINED, - TPM_SHORT, /* 240 */ - TPM_UNDEFINED, - TPM_MEDIUM, -}; - -static void user_reader_timeout(unsigned long ptr) -{ - struct tpm_chip *chip = (struct tpm_chip *) ptr; - - schedule_work(&chip->work); -} - -static void timeout_work(void *ptr) -{ - struct tpm_chip *chip = ptr; - - down(&chip->buffer_mutex); - atomic_set(&chip->data_pending, 0); -#ifndef CONFIG_XEN - memset(chip->data_buffer, 0, TPM_BUFSIZE); -#else - memset(chip->data_buffer, 0, get_chip_buffersize(chip)); -#endif - up(&chip->buffer_mutex); -} - -/* - * Returns max number of jiffies to wait - */ -unsigned long tpm_calc_ordinal_duration(struct tpm_chip *chip, - u32 ordinal) -{ - int duration_idx = TPM_UNDEFINED; - int duration = 0; - - if (ordinal < TPM_MAX_ORDINAL) - duration_idx = tpm_ordinal_duration[ordinal]; - else if ((ordinal & TPM_PROTECTED_ORDINAL_MASK) < - TPM_MAX_PROTECTED_ORDINAL) - duration_idx = - tpm_protected_ordinal_duration[ordinal & - TPM_PROTECTED_ORDINAL_MASK]; - - if (duration_idx != TPM_UNDEFINED) - duration = chip->vendor.duration[duration_idx]; - if (duration <= 0) - return 2 * 60 * HZ; - else - return duration; -} -EXPORT_SYMBOL_GPL(tpm_calc_ordinal_duration); - -/* - * Internal kernel interface to transmit TPM commands - */ -static ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf, - size_t bufsiz) -{ - ssize_t rc; - u32 count, ordinal; - unsigned long stop; - - count = be32_to_cpu(*((__be32 *) (buf + 2))); - ordinal = be32_to_cpu(*((__be32 *) (buf + 6))); - if (count == 0) - return -ENODATA; - if (count > bufsiz) { - dev_err(chip->dev, - "invalid count value %x %zx \n", count, bufsiz); - return -E2BIG; - } - - down(&chip->tpm_mutex); - - if ((rc = chip->vendor.send(chip, (u8 *) buf, count)) < 0) { - dev_err(chip->dev, - "tpm_transmit: tpm_send: error %zd\n", rc); - goto out; - } - - if (chip->vendor.irq) - goto out_recv; - - stop = jiffies + tpm_calc_ordinal_duration(chip, ordinal); - do { - u8 status = chip->vendor.status(chip); - if ((status & chip->vendor.req_complete_mask) == - chip->vendor.req_complete_val) - goto out_recv; - - if ((status == chip->vendor.req_canceled)) { - dev_err(chip->dev, "Operation Canceled\n"); - rc = -ECANCELED; - goto out; - } - - msleep(TPM_TIMEOUT); /* CHECK */ - rmb(); - } while (time_before(jiffies, stop)); - - chip->vendor.cancel(chip); - dev_err(chip->dev, "Operation Timed out\n"); - rc = -ETIME; - goto out; - -out_recv: - rc = chip->vendor.recv(chip, (u8 *) buf, bufsiz); - if (rc < 0) - dev_err(chip->dev, - "tpm_transmit: tpm_recv: error %zd\n", rc); -out: - up(&chip->tpm_mutex); - return rc; -} - -#define TPM_DIGEST_SIZE 20 -#define TPM_ERROR_SIZE 10 -#define TPM_RET_CODE_IDX 6 -#define TPM_GET_CAP_RET_SIZE_IDX 10 -#define TPM_GET_CAP_RET_UINT32_1_IDX 14 -#define TPM_GET_CAP_RET_UINT32_2_IDX 18 -#define TPM_GET_CAP_RET_UINT32_3_IDX 22 -#define TPM_GET_CAP_RET_UINT32_4_IDX 26 -#define TPM_GET_CAP_PERM_DISABLE_IDX 16 -#define TPM_GET_CAP_PERM_INACTIVE_IDX 18 -#define TPM_GET_CAP_RET_BOOL_1_IDX 14 -#define TPM_GET_CAP_TEMP_INACTIVE_IDX 16 - -#define TPM_CAP_IDX 13 -#define TPM_CAP_SUBCAP_IDX 21 - -enum tpm_capabilities { - TPM_CAP_FLAG = 4, - TPM_CAP_PROP = 5, -}; - -enum tpm_sub_capabilities { - TPM_CAP_PROP_PCR = 0x1, - TPM_CAP_PROP_MANUFACTURER = 0x3, - TPM_CAP_FLAG_PERM = 0x8, - TPM_CAP_FLAG_VOL = 0x9, - TPM_CAP_PROP_OWNER = 0x11, - TPM_CAP_PROP_TIS_TIMEOUT = 0x15, - TPM_CAP_PROP_TIS_DURATION = 0x20, -}; - -/* - * This is a semi generic GetCapability command for use - * with the capability type TPM_CAP_PROP or TPM_CAP_FLAG - * and their associated sub_capabilities. - */ - -static const u8 tpm_cap[] = { - 0, 193, /* TPM_TAG_RQU_COMMAND */ - 0, 0, 0, 22, /* length */ - 0, 0, 0, 101, /* TPM_ORD_GetCapability */ - 0, 0, 0, 0, /* TPM_CAP_<TYPE> */ - 0, 0, 0, 4, /* TPM_CAP_SUB_<TYPE> size */ - 0, 0, 1, 0 /* TPM_CAP_SUB_<TYPE> */ -}; - -static ssize_t transmit_cmd(struct tpm_chip *chip, u8 *data, int len, - char *desc) -{ - int err; - - len = tpm_transmit(chip, data, len); - if (len < 0) - return len; - if (len == TPM_ERROR_SIZE) { - err = be32_to_cpu(*((__be32 *) (data + TPM_RET_CODE_IDX))); - dev_dbg(chip->dev, "A TPM error (%d) occurred %s\n", err, desc); - return err; - } - return 0; -} - -void tpm_gen_interrupt(struct tpm_chip *chip) -{ - u8 data[max_t(int, ARRAY_SIZE(tpm_cap), 30)]; - ssize_t rc; - - memcpy(data, tpm_cap, sizeof(tpm_cap)); - data[TPM_CAP_IDX] = TPM_CAP_PROP; - data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_TIS_TIMEOUT; - - rc = transmit_cmd(chip, data, sizeof(data), - "attempting to determine the timeouts"); -} -EXPORT_SYMBOL_GPL(tpm_gen_interrupt); - -void tpm_get_timeouts(struct tpm_chip *chip) -{ - u8 data[max_t(int, ARRAY_SIZE(tpm_cap), 30)]; - ssize_t rc; - u32 timeout; - - memcpy(data, tpm_cap, sizeof(tpm_cap)); - data[TPM_CAP_IDX] = TPM_CAP_PROP; - data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_TIS_TIMEOUT; - - rc = transmit_cmd(chip, data, sizeof(data), - "attempting to determine the timeouts"); - if (rc) - goto duration; - - if (be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_SIZE_IDX))) - != 4 * sizeof(u32)) - goto duration; - - /* Don't overwrite default if value is 0 */ - timeout = - be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_1_IDX))); - if (timeout) - chip->vendor.timeout_a = msecs_to_jiffies(timeout); - timeout = - be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_2_IDX))); - if (timeout) - chip->vendor.timeout_b = msecs_to_jiffies(timeout); - timeout = - be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_3_IDX))); - if (timeout) - chip->vendor.timeout_c = msecs_to_jiffies(timeout); - timeout = - be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_4_IDX))); - if (timeout) - chip->vendor.timeout_d = msecs_to_jiffies(timeout); - -duration: - memcpy(data, tpm_cap, sizeof(tpm_cap)); - data[TPM_CAP_IDX] = TPM_CAP_PROP; - data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_TIS_DURATION; - - rc = transmit_cmd(chip, data, sizeof(data), - "attempting to determine the durations"); - if (rc) - return; - - if (be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_SIZE_IDX))) - != 3 * sizeof(u32)) - return; - - chip->vendor.duration[TPM_SHORT] = - msecs_to_jiffies(be32_to_cpu - (*((__be32 *) (data + - TPM_GET_CAP_RET_UINT32_1_IDX)))); - chip->vendor.duration[TPM_MEDIUM] = - msecs_to_jiffies(be32_to_cpu - (*((__be32 *) (data + - TPM_GET_CAP_RET_UINT32_2_IDX)))); - chip->vendor.duration[TPM_LONG] = - msecs_to_jiffies(be32_to_cpu - (*((__be32 *) (data + - TPM_GET_CAP_RET_UINT32_3_IDX)))); -} -EXPORT_SYMBOL_GPL(tpm_get_timeouts); - -void tpm_continue_selftest(struct tpm_chip *chip) -{ - u8 data[] = { - 0, 193, /* TPM_TAG_RQU_COMMAND */ - 0, 0, 0, 10, /* length */ - 0, 0, 0, 83, /* TPM_ORD_GetCapability */ - }; - - tpm_transmit(chip, data, sizeof(data)); -} -EXPORT_SYMBOL_GPL(tpm_continue_selftest); - -ssize_t tpm_show_enabled(struct device * dev, struct device_attribute * attr, - char *buf) -{ - u8 data[max_t(int, ARRAY_SIZE(tpm_cap), 35)]; - ssize_t rc; - - struct tpm_chip *chip = dev_get_drvdata(dev); - if (chip == NULL) - return -ENODEV; - - memcpy(data, tpm_cap, sizeof(tpm_cap)); - data[TPM_CAP_IDX] = TPM_CAP_FLAG; - data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_FLAG_PERM; - - rc = transmit_cmd(chip, data, sizeof(data), - "attemtping to determine the permanent state"); - if (rc) - return 0; - return sprintf(buf, "%d\n", !data[TPM_GET_CAP_PERM_DISABLE_IDX]); -} -EXPORT_SYMBOL_GPL(tpm_show_enabled); - -ssize_t tpm_show_active(struct device * dev, struct device_attribute * attr, - char *buf) -{ - u8 data[max_t(int, ARRAY_SIZE(tpm_cap), 35)]; - ssize_t rc; - - struct tpm_chip *chip = dev_get_drvdata(dev); - if (chip == NULL) - return -ENODEV; - - memcpy(data, tpm_cap, sizeof(tpm_cap)); - data[TPM_CAP_IDX] = TPM_CAP_FLAG; - data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_FLAG_PERM; - - rc = transmit_cmd(chip, data, sizeof(data), - "attemtping to determine the permanent state"); - if (rc) - return 0; - return sprintf(buf, "%d\n", !data[TPM_GET_CAP_PERM_INACTIVE_IDX]); -} -EXPORT_SYMBOL_GPL(tpm_show_active); - -ssize_t tpm_show_owned(struct device * dev, struct device_attribute * attr, - char *buf) -{ - u8 data[sizeof(tpm_cap)]; - ssize_t rc; - - struct tpm_chip *chip = dev_get_drvdata(dev); - if (chip == NULL) - return -ENODEV; - - memcpy(data, tpm_cap, sizeof(tpm_cap)); - data[TPM_CAP_IDX] = TPM_CAP_PROP; - data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_OWNER; - - rc = transmit_cmd(chip, data, sizeof(data), - "attempting to determine the owner state"); - if (rc) - return 0; - return sprintf(buf, "%d\n", data[TPM_GET_CAP_RET_BOOL_1_IDX]); -} -EXPORT_SYMBOL_GPL(tpm_show_owned); - -ssize_t tpm_show_temp_deactivated(struct device * dev, - struct device_attribute * attr, char *buf) -{ - u8 data[sizeof(tpm_cap)]; - ssize_t rc; - - struct tpm_chip *chip = dev_get_drvdata(dev); - if (chip == NULL) - return -ENODEV; - - memcpy(data, tpm_cap, sizeof(tpm_cap)); - data[TPM_CAP_IDX] = TPM_CAP_FLAG; - data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_FLAG_VOL; - - rc = transmit_cmd(chip, data, sizeof(data), - "attempting to determine the temporary state"); - if (rc) - return 0; - return sprintf(buf, "%d\n", data[TPM_GET_CAP_TEMP_INACTIVE_IDX]); -} -EXPORT_SYMBOL_GPL(tpm_show_temp_deactivated); - -static const u8 pcrread[] = { - 0, 193, /* TPM_TAG_RQU_COMMAND */ - 0, 0, 0, 14, /* length */ - 0, 0, 0, 21, /* TPM_ORD_PcrRead */ - 0, 0, 0, 0 /* PCR index */ -}; - -ssize_t tpm_show_pcrs(struct device *dev, struct device_attribute *attr, - char *buf) -{ - u8 data[max_t(int, max(ARRAY_SIZE(tpm_cap), ARRAY_SIZE(pcrread)), 30)]; - ssize_t rc; - int i, j, num_pcrs; - __be32 index; - char *str = buf; - - struct tpm_chip *chip = dev_get_drvdata(dev); - if (chip == NULL) - return -ENODEV; - - memcpy(data, tpm_cap, sizeof(tpm_cap)); - data[TPM_CAP_IDX] = TPM_CAP_PROP; - data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_PCR; - - rc = transmit_cmd(chip, data, sizeof(data), - "attempting to determine the number of PCRS"); - if (rc) - return 0; - - num_pcrs = be32_to_cpu(*((__be32 *) (data + 14))); - for (i = 0; i < num_pcrs; i++) { - memcpy(data, pcrread, sizeof(pcrread)); - index = cpu_to_be32(i); - memcpy(data + 10, &index, 4); - rc = transmit_cmd(chip, data, sizeof(data), - "attempting to read a PCR"); - if (rc) - goto out; - str += sprintf(str, "PCR-%02d: ", i); - for (j = 0; j < TPM_DIGEST_SIZE; j++) - str += sprintf(str, "%02X ", *(data + 10 + j)); - str += sprintf(str, "\n"); - } -out: - return str - buf; -} -EXPORT_SYMBOL_GPL(tpm_show_pcrs); - -#define READ_PUBEK_RESULT_SIZE 314 -static const u8 readpubek[] = { - 0, 193, /* TPM_TAG_RQU_COMMAND */ - 0, 0, 0, 30, /* length */ - 0, 0, 0, 124, /* TPM_ORD_ReadPubek */ -}; - -ssize_t tpm_show_pubek(struct device *dev, struct device_attribute *attr, - char *buf) -{ - u8 *data; - ssize_t err; - int i, rc; - char *str = buf; - - struct tpm_chip *chip = dev_get_drvdata(dev); - if (chip == NULL) - return -ENODEV; - - data = kzalloc(READ_PUBEK_RESULT_SIZE, GFP_KERNEL); - if (!data) - return -ENOMEM; - - memcpy(data, readpubek, sizeof(readpubek)); - - err = transmit_cmd(chip, data, READ_PUBEK_RESULT_SIZE, - "attempting to read the PUBEK"); - if (err) - goto out; - - /* - ignore header 10 bytes - algorithm 32 bits (1 == RSA ) - encscheme 16 bits - sigscheme 16 bits - parameters (RSA 12->bytes: keybit, #primes, expbit) - keylenbytes 32 bits - 256 byte modulus - ignore checksum 20 bytes - */ - - str += - sprintf(str, - "Algorithm: %02X %02X %02X %02X\nEncscheme: %02X %02X\n" - "Sigscheme: %02X %02X\nParameters: %02X %02X %02X %02X" - " %02X %02X %02X %02X %02X %02X %02X %02X\n" - "Modulus length: %d\nModulus: \n", - data[10], data[11], data[12], data[13], data[14], - data[15], data[16], data[17], data[22], data[23], - data[24], data[25], data[26], data[27], data[28], - data[29], data[30], data[31], data[32], data[33], - be32_to_cpu(*((__be32 *) (data + 34)))); - - for (i = 0; i < 256; i++) { - str += sprintf(str, "%02X ", data[i + 38]); - if ((i + 1) % 16 == 0) - str += sprintf(str, "\n"); - } -out: - rc = str - buf; - kfree(data); - return rc; -} -EXPORT_SYMBOL_GPL(tpm_show_pubek); - -#define CAP_VERSION_1_1 6 -#define CAP_VERSION_1_2 0x1A -#define CAP_VERSION_IDX 13 -static const u8 cap_version[] = { - 0, 193, /* TPM_TAG_RQU_COMMAND */ - 0, 0, 0, 18, /* length */ - 0, 0, 0, 101, /* TPM_ORD_GetCapability */ - 0, 0, 0, 0, - 0, 0, 0, 0 -}; - -ssize_t tpm_show_caps(struct device *dev, struct device_attribute *attr, - char *buf) -{ - u8 data[max_t(int, max(ARRAY_SIZE(tpm_cap), ARRAY_SIZE(cap_version)), 30)]; - ssize_t rc; - char *str = buf; - - struct tpm_chip *chip = dev_get_drvdata(dev); - if (chip == NULL) - return -ENODEV; - - memcpy(data, tpm_cap, sizeof(tpm_cap)); - data[TPM_CAP_IDX] = TPM_CAP_PROP; - data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_MANUFACTURER; - - rc = transmit_cmd(chip, data, sizeof(data), - "attempting to determine the manufacturer"); - if (rc) - return 0; - - str += sprintf(str, "Manufacturer: 0x%x\n", - be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_1_IDX)))); - - memcpy(data, cap_version, sizeof(cap_version)); - data[CAP_VERSION_IDX] = CAP_VERSION_1_1; - rc = transmit_cmd(chip, data, sizeof(data), - "attempting to determine the 1.1 version"); - if (rc) - goto out; - - str += sprintf(str, - "TCG version: %d.%d\nFirmware version: %d.%d\n", - (int) data[14], (int) data[15], (int) data[16], - (int) data[17]); - -out: - return str - buf; -} -EXPORT_SYMBOL_GPL(tpm_show_caps); - -ssize_t tpm_show_caps_1_2(struct device * dev, - struct device_attribute * attr, char *buf) -{ - u8 data[max_t(int, max(ARRAY_SIZE(tpm_cap), ARRAY_SIZE(cap_version)), 30)]; - ssize_t len; - char *str = buf; - - struct tpm_chip *chip = dev_get_drvdata(dev); - if (chip == NULL) - return -ENODEV; - - memcpy(data, tpm_cap, sizeof(tpm_cap)); - data[TPM_CAP_IDX] = TPM_CAP_PROP; - data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_MANUFACTURER; - - if ((len = tpm_transmit(chip, data, sizeof(data))) <= - TPM_ERROR_SIZE) { - dev_dbg(chip->dev, "A TPM error (%d) occurred " - "attempting to determine the manufacturer\n", - be32_to_cpu(*((__be32 *) (data + TPM_RET_CODE_IDX)))); - return 0; - } - - str += sprintf(str, "Manufacturer: 0x%x\n", - be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_1_IDX)))); - - memcpy(data, cap_version, sizeof(cap_version)); - data[CAP_VERSION_IDX] = CAP_VERSION_1_2; - - if ((len = tpm_transmit(chip, data, sizeof(data))) <= - TPM_ERROR_SIZE) { - dev_err(chip->dev, "A TPM error (%d) occurred " - "attempting to determine the 1.2 version\n", - be32_to_cpu(*((__be32 *) (data + TPM_RET_CODE_IDX)))); - goto out; - } - str += sprintf(str, - "TCG version: %d.%d\nFirmware version: %d.%d\n", - (int) data[16], (int) data[17], (int) data[18], - (int) data[19]); - -out: - return str - buf; -} -EXPORT_SYMBOL_GPL(tpm_show_caps_1_2); - -ssize_t tpm_store_cancel(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct tpm_chip *chip = dev_get_drvdata(dev); - if (chip == NULL) - return 0; - - chip->vendor.cancel(chip); - return count; -} -EXPORT_SYMBOL_GPL(tpm_store_cancel); - -/* - * Device file system interface to the TPM - */ -int tpm_open(struct inode *inode, struct file *file) -{ - int rc = 0, minor = iminor(inode); - struct tpm_chip *chip = NULL, *pos; - - spin_lock(&driver_lock); - - list_for_each_entry(pos, &tpm_chip_list, list) { - if (pos->vendor.miscdev.minor == minor) { - chip = pos; - break; - } - } - - if (chip == NULL) { - rc = -ENODEV; - goto err_out; - } - - if (chip->num_opens) { - dev_dbg(chip->dev, "Another process owns this TPM\n"); - rc = -EBUSY; - goto err_out; - } - - chip->num_opens++; - get_device(chip->dev); - - spin_unlock(&driver_lock); - -#ifndef CONFIG_XEN - chip->data_buffer = kmalloc(TPM_BUFSIZE * sizeof(u8), GFP_KERNEL); -#else - chip->data_buffer = kmalloc(get_chip_buffersize(chip) * sizeof(u8), - GFP_KERNEL); -#endif - if (chip->data_buffer == NULL) { - chip->num_opens--; - put_device(chip->dev); - return -ENOMEM; - } - - atomic_set(&chip->data_pending, 0); - - file->private_data = chip; - return 0; - -err_out: - spin_unlock(&driver_lock); - return rc; -} -EXPORT_SYMBOL_GPL(tpm_open); - -int tpm_release(struct inode *inode, struct file *file) -{ - struct tpm_chip *chip = file->private_data; - - spin_lock(&driver_lock); - file->private_data = NULL; - chip->num_opens--; - del_singleshot_timer_sync(&chip->user_read_timer); - flush_scheduled_work(); - atomic_set(&chip->data_pending, 0); - put_device(chip->dev); - kfree(chip->data_buffer); - spin_unlock(&driver_lock); - return 0; -} -EXPORT_SYMBOL_GPL(tpm_release); - -ssize_t tpm_write(struct file *file, const char __user *buf, - size_t size, loff_t *off) -{ - struct tpm_chip *chip = file->private_data; - int in_size = size, out_size; - - /* cannot perform a write until the read has cleared - either via tpm_read or a user_read_timer timeout */ - while (atomic_read(&chip->data_pending) != 0) - msleep(TPM_TIMEOUT); - - down(&chip->buffer_mutex); - -#ifndef CONFIG_XEN - if (in_size > TPM_BUFSIZE) - in_size = TPM_BUFSIZE; -#else - if (in_size > get_chip_buffersize(chip)) - in_size = get_chip_buffersize(chip); -#endif - - if (copy_from_user - (chip->data_buffer, (void __user *) buf, in_size)) { - up(&chip->buffer_mutex); - return -EFAULT; - } - - /* atomic tpm command send and result receive */ -#ifndef CONFIG_XEN - out_size = tpm_transmit(chip, chip->data_buffer, TPM_BUFSIZE); -#else - out_size = tpm_transmit(chip, chip->data_buffer, - get_chip_buffersize(chip)); -#endif - - atomic_set(&chip->data_pending, out_size); -#ifdef CONFIG_XEN - atomic_set(&chip->data_position, 0); -#endif - up(&chip->buffer_mutex); - - /* Set a timeout by which the reader must come claim the result */ - mod_timer(&chip->user_read_timer, jiffies + (60 * HZ)); - - return in_size; -} -EXPORT_SYMBOL_GPL(tpm_write); - -ssize_t tpm_read(struct file *file, char __user *buf, - size_t size, loff_t *off) -{ - struct tpm_chip *chip = file->private_data; - int ret_size; -#ifdef CONFIG_XEN - int pos, pending = 0; -#endif - -#ifndef CONFIG_XEN - del_singleshot_timer_sync(&chip->user_read_timer); - flush_scheduled_work(); -#endif - ret_size = atomic_read(&chip->data_pending); -#ifndef CONFIG_XEN - atomic_set(&chip->data_pending, 0); -#endif - if (ret_size > 0) { /* relay data */ - if (size < ret_size) - ret_size = size; - -#ifdef CONFIG_XEN - pos = atomic_read(&chip->data_position); -#endif - down(&chip->buffer_mutex); -#ifndef CONFIG_XEN - if (copy_to_user(buf, chip->data_buffer, ret_size)) -#else - if (copy_to_user(buf, &chip->data_buffer[pos], ret_size)) { -#endif - ret_size = -EFAULT; -#ifdef CONFIG_XEN - } else { - pending = atomic_read(&chip->data_pending) - ret_size; - if ( pending ) { - atomic_set(&chip->data_pending, pending); - atomic_set(&chip->data_position, - pos+ret_size); - } - } -#endif - up(&chip->buffer_mutex); - } - -#ifdef CONFIG_XEN - if ( ret_size <= 0 || pending == 0 ) { - atomic_set(&chip->data_pending, 0); - del_singleshot_timer_sync(&chip->user_read_timer); - flush_scheduled_work(); - } -#endif - return ret_size; -} -EXPORT_SYMBOL_GPL(tpm_read); - -void tpm_remove_hardware(struct device *dev) -{ - struct tpm_chip *chip = dev_get_drvdata(dev); - - if (chip == NULL) { - dev_err(dev, "No device data found\n"); - return; - } - - spin_lock(&driver_lock); - - list_del(&chip->list); - - spin_unlock(&driver_lock); - - dev_set_drvdata(dev, NULL); - misc_deregister(&chip->vendor.miscdev); - kfree(chip->vendor.miscdev.name); - - sysfs_remove_group(&dev->kobj, chip->vendor.attr_group); - tpm_bios_log_teardown(chip->bios_dir); - - clear_bit(chip->dev_num, dev_mask); - - kfree(chip); - - put_device(dev); -} -EXPORT_SYMBOL_GPL(tpm_remove_hardware); - -static u8 savestate[] = { - 0, 193, /* TPM_TAG_RQU_COMMAND */ - 0, 0, 0, 10, /* blob length (in bytes) */ - 0, 0, 0, 152 /* TPM_ORD_SaveState */ -}; - -/* - * We are about to suspend. Save the TPM state - * so that it can be restored. - */ -int tpm_pm_suspend(struct device *dev, pm_message_t pm_state) -{ - struct tpm_chip *chip = dev_get_drvdata(dev); - if (chip == NULL) - return -ENODEV; - - tpm_transmit(chip, savestate, sizeof(savestate)); - return 0; -} -EXPORT_SYMBOL_GPL(tpm_pm_suspend); - -/* - * Resume from a power safe. The BIOS already restored - * the TPM state. - */ -int tpm_pm_resume(struct device *dev) -{ - struct tpm_chip *chip = dev_get_drvdata(dev); - - if (chip == NULL) - return -ENODEV; - - return 0; -} -EXPORT_SYMBOL_GPL(tpm_pm_resume); - -/* - * Called from tpm_<specific>.c probe function only for devices - * the driver has determined it should claim. Prior to calling - * this function the specific probe function has called pci_enable_device - * upon errant exit from this function specific probe function should call - * pci_disable_device - */ -struct tpm_chip *tpm_register_hardware(struct device *dev, const struct tpm_vendor_specific - *entry) -{ -#define DEVNAME_SIZE 7 - - char *devname; - struct tpm_chip *chip; - - /* Driver specific per-device data */ - chip = kzalloc(sizeof(*chip), GFP_KERNEL); - if (chip == NULL) - return NULL; - - init_MUTEX(&chip->buffer_mutex); - init_MUTEX(&chip->tpm_mutex); - INIT_LIST_HEAD(&chip->list); - - INIT_WORK(&chip->work, timeout_work, chip); - - init_timer(&chip->user_read_timer); - chip->user_read_timer.function = user_reader_timeout; - chip->user_read_timer.data = (unsigned long) chip; - - memcpy(&chip->vendor, entry, sizeof(struct tpm_vendor_specific)); - - chip->dev_num = find_first_zero_bit(dev_mask, TPM_NUM_DEVICES); - - if (chip->dev_num >= TPM_NUM_DEVICES) { - dev_err(dev, "No available tpm device numbers\n"); - kfree(chip); - return NULL; - } else if (chip->dev_num == 0) - chip->vendor.miscdev.minor = TPM_MINOR; - else - chip->vendor.miscdev.minor = MISC_DYNAMIC_MINOR; - - set_bit(chip->dev_num, dev_mask); - - devname = kmalloc(DEVNAME_SIZE, GFP_KERNEL); - scnprintf(devname, DEVNAME_SIZE, "%s%d", "tpm", chip->dev_num); - chip->vendor.miscdev.name = devname; - - chip->vendor.miscdev.dev = dev; - chip->dev = get_device(dev); - - if (misc_register(&chip->vendor.miscdev)) { - dev_err(chip->dev, - "unable to misc_register %s, minor %d\n", - chip->vendor.miscdev.name, - chip->vendor.miscdev.minor); - put_device(dev); - clear_bit(chip->dev_num, dev_mask); - kfree(chip); - kfree(devname); - return NULL; - } - - spin_lock(&driver_lock); - - dev_set_drvdata(dev, chip); - - list_add(&chip->list, &tpm_chip_list); - - spin_unlock(&driver_lock); - - sysfs_create_group(&dev->kobj, chip->vendor.attr_group); - - chip->bios_dir = tpm_bios_log_setup(devname); - - return chip; -} -EXPORT_SYMBOL_GPL(tpm_register_hardware); - -MODULE_AUTHOR("Leendert van Doorn (leendert@xxxxxxxxxxxxxx)"); -MODULE_DESCRIPTION("TPM Driver"); -MODULE_VERSION("2.0"); -MODULE_LICENSE("GPL"); diff -r 04c23c1ef888 -r d907467f08cd linux-2.6-xen-sparse/drivers/char/tpm/tpm.h --- a/linux-2.6-xen-sparse/drivers/char/tpm/tpm.h Sun Feb 18 16:13:13 2007 -0700 +++ b/linux-2.6-xen-sparse/drivers/char/tpm/tpm.h Tue Feb 20 12:58:22 2007 -0700 @@ -25,13 +25,6 @@ #include <linux/miscdevice.h> #include <linux/platform_device.h> #include <linux/io.h> - -#ifdef CONFIG_XEN -enum tpm_bufsize { - TPM_MIN_BUFFERSIZE = 2048, - TPM_MAX_BUFFERSIZE = 64 * 1024, -}; -#endif enum tpm_timeout { TPM_TIMEOUT = 5, /* msecs */ @@ -68,9 +61,6 @@ struct tpm_vendor_specific { const u8 req_complete_mask; const u8 req_complete_val; const u8 req_canceled; -#ifdef CONFIG_XEN - u32 buffersize; -#endif void __iomem *iobase; /* ioremapped address */ unsigned long base; /* TPM base address */ @@ -104,9 +94,6 @@ struct tpm_chip { /* Data passed to and from the tpm via the read/write calls */ u8 *data_buffer; atomic_t data_pending; -#ifdef CONFIG_XEN - atomic_t data_position; -#endif struct semaphore buffer_mutex; struct timer_list user_read_timer; /* user needs to claim result */ @@ -138,17 +125,6 @@ static inline void tpm_write_index(int b } #ifdef CONFIG_XEN -static inline u32 get_chip_buffersize(struct tpm_chip *chip) -{ - u32 size = chip->vendor.buffersize; - if (size > TPM_MAX_BUFFERSIZE) { - return TPM_MAX_BUFFERSIZE; - } else if (size < TPM_MIN_BUFFERSIZE) { - return TPM_MIN_BUFFERSIZE; - } - return size; -} - static inline void *chip_get_private(const struct tpm_chip *chip) { return chip->priv; diff -r 04c23c1ef888 -r d907467f08cd linux-2.6-xen-sparse/drivers/char/tpm/tpm_vtpm.c --- a/linux-2.6-xen-sparse/drivers/char/tpm/tpm_vtpm.c Sun Feb 18 16:13:13 2007 -0700 +++ b/linux-2.6-xen-sparse/drivers/char/tpm/tpm_vtpm.c Tue Feb 20 12:58:22 2007 -0700 @@ -519,9 +519,6 @@ struct tpm_chip *init_vtpm(struct device vtpms->tpmvd = tvd; vtpms->tpm_private = tp; - if (tvd) - tpm_vtpm.buffersize = tvd->max_tx_size; - chip = tpm_register_hardware(dev, &tpm_vtpm); if (!chip) { rc = -ENODEV; diff -r 04c23c1ef888 -r d907467f08cd linux-2.6-xen-sparse/drivers/xen/balloon/balloon.c --- a/linux-2.6-xen-sparse/drivers/xen/balloon/balloon.c Sun Feb 18 16:13:13 2007 -0700 +++ b/linux-2.6-xen-sparse/drivers/xen/balloon/balloon.c Tue Feb 20 12:58:22 2007 -0700 @@ -60,7 +60,7 @@ static struct proc_dir_entry *balloon_pd static struct proc_dir_entry *balloon_pde; #endif -static DECLARE_MUTEX(balloon_mutex); +static DEFINE_MUTEX(balloon_mutex); /* * Protects atomic reservation decrease/increase against concurrent increases. @@ -321,7 +321,7 @@ static void balloon_process(void *unused int need_sleep = 0; long credit; - down(&balloon_mutex); + mutex_lock(&balloon_mutex); do { credit = current_target() - bs.current_pages; @@ -340,7 +340,7 @@ static void balloon_process(void *unused if (current_target() != bs.current_pages) mod_timer(&balloon_timer, jiffies + HZ); - up(&balloon_mutex); + mutex_unlock(&balloon_mutex); } /* Resets the Xen limit, sets new target, and kicks off processing. */ diff -r 04c23c1ef888 -r d907467f08cd linux-2.6-xen-sparse/drivers/xen/blkback/interface.c --- a/linux-2.6-xen-sparse/drivers/xen/blkback/interface.c Sun Feb 18 16:13:13 2007 -0700 +++ b/linux-2.6-xen-sparse/drivers/xen/blkback/interface.c Tue Feb 20 12:58:22 2007 -0700 @@ -58,15 +58,12 @@ static int map_frontend_page(blkif_t *bl static int map_frontend_page(blkif_t *blkif, unsigned long shared_page) { struct gnttab_map_grant_ref op; - int ret; gnttab_set_map_op(&op, (unsigned long)blkif->blk_ring_area->addr, GNTMAP_host_map, shared_page, blkif->domid); - lock_vm_area(blkif->blk_ring_area); - ret = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1); - unlock_vm_area(blkif->blk_ring_area); - BUG_ON(ret); + if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1)) + BUG(); if (op.status) { DPRINTK(" Grant table operation failure !\n"); @@ -82,15 +79,12 @@ static void unmap_frontend_page(blkif_t static void unmap_frontend_page(blkif_t *blkif) { struct gnttab_unmap_grant_ref op; - int ret; gnttab_set_unmap_op(&op, (unsigned long)blkif->blk_ring_area->addr, GNTMAP_host_map, blkif->shmem_handle); - lock_vm_area(blkif->blk_ring_area); - ret = HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1); - unlock_vm_area(blkif->blk_ring_area); - BUG_ON(ret); + if (HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1)) + BUG(); } int blkif_map(blkif_t *blkif, unsigned long shared_page, unsigned int evtchn) diff -r 04c23c1ef888 -r d907467f08cd linux-2.6-xen-sparse/drivers/xen/blktap/interface.c --- a/linux-2.6-xen-sparse/drivers/xen/blktap/interface.c Sun Feb 18 16:13:13 2007 -0700 +++ b/linux-2.6-xen-sparse/drivers/xen/blktap/interface.c Tue Feb 20 12:58:22 2007 -0700 @@ -58,15 +58,12 @@ static int map_frontend_page(blkif_t *bl static int map_frontend_page(blkif_t *blkif, unsigned long shared_page) { struct gnttab_map_grant_ref op; - int ret; gnttab_set_map_op(&op, (unsigned long)blkif->blk_ring_area->addr, GNTMAP_host_map, shared_page, blkif->domid); - lock_vm_area(blkif->blk_ring_area); - ret = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1); - unlock_vm_area(blkif->blk_ring_area); - BUG_ON(ret); + if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1)) + BUG(); if (op.status) { DPRINTK(" Grant table operation failure !\n"); @@ -82,15 +79,12 @@ static void unmap_frontend_page(blkif_t static void unmap_frontend_page(blkif_t *blkif) { struct gnttab_unmap_grant_ref op; - int ret; gnttab_set_unmap_op(&op, (unsigned long)blkif->blk_ring_area->addr, GNTMAP_host_map, blkif->shmem_handle); - lock_vm_area(blkif->blk_ring_area); - ret = HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1); - unlock_vm_area(blkif->blk_ring_area); - BUG_ON(ret); + if (HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1)) + BUG(); } int tap_blkif_map(blkif_t *blkif, unsigned long shared_page, diff -r 04c23c1ef888 -r d907467f08cd linux-2.6-xen-sparse/drivers/xen/core/gnttab.c --- a/linux-2.6-xen-sparse/drivers/xen/core/gnttab.c Sun Feb 18 16:13:13 2007 -0700 +++ b/linux-2.6-xen-sparse/drivers/xen/core/gnttab.c Tue Feb 20 12:58:22 2007 -0700 @@ -3,7 +3,7 @@ * * Granting foreign access to our memory reservation. * - * Copyright (c) 2005, Christopher Clark + * Copyright (c) 2005-2006, Christopher Clark * Copyright (c) 2004-2005, K A Fraser * * This program is free software; you can redistribute it and/or @@ -35,7 +35,6 @@ #include <linux/module.h> #include <linux/sched.h> #include <linux/mm.h> -#include <linux/vmalloc.h> #include <xen/interface/xen.h> #include <xen/gnttab.h> #include <asm/pgtable.h> @@ -43,6 +42,7 @@ #include <asm/synch_bitops.h> #include <asm/io.h> #include <xen/interface/memory.h> +#include <xen/driver_util.h> #ifdef HAVE_XEN_PLATFORM_COMPAT_H #include <xen/platform-compat.h> @@ -50,37 +50,51 @@ /* External tools reserve first few grant table entries. */ #define NR_RESERVED_ENTRIES 8 - -#define NR_GRANT_ENTRIES \ - (NR_GRANT_FRAMES * PAGE_SIZE / sizeof(struct grant_entry)) -#define GNTTAB_LIST_END (NR_GRANT_ENTRIES + 1) - -static grant_ref_t gnttab_list[NR_GRANT_ENTRIES]; +#define GNTTAB_LIST_END 0xffffffff +#define GREFS_PER_GRANT_FRAME (PAGE_SIZE / sizeof(grant_entry_t)) + +static grant_ref_t **gnttab_list; +static unsigned int nr_grant_frames; +static unsigned int boot_max_nr_grant_frames; static int gnttab_free_count; static grant_ref_t gnttab_free_head; static DEFINE_SPINLOCK(gnttab_list_lock); static struct grant_entry *shared; +#ifndef CONFIG_XEN +static unsigned long resume_frames; +#endif static struct gnttab_free_callback *gnttab_free_callback_list; +static int gnttab_expand(unsigned int req_entries); + +#define RPP (PAGE_SIZE / sizeof(grant_ref_t)) +#define gnttab_entry(entry) (gnttab_list[(entry) / RPP][(entry) % RPP]) + static int get_free_entries(int count) { unsigned long flags; - int ref; + int ref, rc; grant_ref_t head; + spin_lock_irqsave(&gnttab_list_lock, flags); - if (gnttab_free_count < count) { + + if ((gnttab_free_count < count) && + ((rc = gnttab_expand(count - gnttab_free_count)) < 0)) { spin_unlock_irqrestore(&gnttab_list_lock, flags); - return -1; - } + return rc; + } + ref = head = gnttab_free_head; gnttab_free_count -= count; while (count-- > 1) - head = gnttab_list[head]; - gnttab_free_head = gnttab_list[head]; - gnttab_list[head] = GNTTAB_LIST_END; + head = gnttab_entry(head); + gnttab_free_head = gnttab_entry(head); + gnttab_entry(head) = GNTTAB_LIST_END; + spin_unlock_irqrestore(&gnttab_list_lock, flags); + return ref; } @@ -116,7 +130,7 @@ static void put_free_entry(grant_ref_t r { unsigned long flags; spin_lock_irqsave(&gnttab_list_lock, flags); - gnttab_list[ref] = gnttab_free_head; + gnttab_entry(ref) = gnttab_free_head; gnttab_free_head = ref; gnttab_free_count++; check_free_callbacks(); @@ -132,7 +146,7 @@ int gnttab_grant_foreign_access(domid_t { int ref; - if (unlikely((ref = get_free_entry()) == -1)) + if (unlikely((ref = get_free_entry()) < 0)) return -ENOSPC; shared[ref].frame = frame; @@ -202,7 +216,7 @@ int gnttab_grant_foreign_transfer(domid_ { int ref; - if (unlikely((ref = get_free_entry()) == -1)) + if (unlikely((ref = get_free_entry()) < 0)) return -ENOSPC; gnttab_grant_foreign_transfer_ref(ref, domid, pfn); @@ -273,11 +287,11 @@ void gnttab_free_grant_references(grant_ return; spin_lock_irqsave(&gnttab_list_lock, flags); ref = head; - while (gnttab_list[ref] != GNTTAB_LIST_END) { - ref = gnttab_list[ref]; + while (gnttab_entry(ref) != GNTTAB_LIST_END) { + ref = gnttab_entry(ref); count++; } - gnttab_list[ref] = gnttab_free_head; + gnttab_entry(ref) = gnttab_free_head; gnttab_free_head = head; gnttab_free_count += count; check_free_callbacks(); @@ -289,7 +303,7 @@ int gnttab_alloc_grant_references(u16 co { int h = get_free_entries(count); - if (h == -1) + if (h < 0) return -ENOSPC; *head = h; @@ -309,7 +323,7 @@ int gnttab_claim_grant_reference(grant_r grant_ref_t g = *private_head; if (unlikely(g == GNTTAB_LIST_END)) return -ENOSPC; - *private_head = gnttab_list[g]; + *private_head = gnttab_entry(g); return g; } EXPORT_SYMBOL_GPL(gnttab_claim_grant_reference); @@ -317,7 +331,7 @@ void gnttab_release_grant_reference(gran void gnttab_release_grant_reference(grant_ref_t *private_head, grant_ref_t release) { - gnttab_list[release] = *private_head; + gnttab_entry(release) = *private_head; *private_head = release; } EXPORT_SYMBOL_GPL(gnttab_release_grant_reference); @@ -356,6 +370,64 @@ void gnttab_cancel_free_callback(struct } EXPORT_SYMBOL_GPL(gnttab_cancel_free_callback); +static int grow_gnttab_list(unsigned int more_frames) +{ + unsigned int new_nr_grant_frames, extra_entries, i; + + new_nr_grant_frames = nr_grant_frames + more_frames; + extra_entries = more_frames * GREFS_PER_GRANT_FRAME; + + for (i = nr_grant_frames; i < new_nr_grant_frames; i++) + { + gnttab_list[i] = (grant_ref_t *)__get_free_page(GFP_ATOMIC); + if (!gnttab_list[i]) + goto grow_nomem; + } + + + for (i = GREFS_PER_GRANT_FRAME * nr_grant_frames; + i < GREFS_PER_GRANT_FRAME * new_nr_grant_frames - 1; i++) + gnttab_entry(i) = i + 1; + + gnttab_entry(i) = gnttab_free_head; + gnttab_free_head = GREFS_PER_GRANT_FRAME * nr_grant_frames; + gnttab_free_count += extra_entries; + + nr_grant_frames = new_nr_grant_frames; + + check_free_callbacks(); + + return 0; + +grow_nomem: + for ( ; i >= nr_grant_frames; i--) + free_page((unsigned long) gnttab_list[i]); + return -ENOMEM; +} + +static unsigned int __max_nr_grant_frames(void) +{ + struct gnttab_query_size query; + int rc; + + query.dom = DOMID_SELF; + + rc = HYPERVISOR_grant_table_op(GNTTABOP_query_size, &query, 1); + if ((rc < 0) || (query.status != GNTST_okay)) + return 4; /* Legacy max supported number of frames */ + + return query.max_nr_frames; +} + +static inline unsigned int max_nr_grant_frames(void) +{ + unsigned int xen_max = __max_nr_grant_frames(); + + if (xen_max > boot_max_nr_grant_frames) + return boot_max_nr_grant_frames; + return xen_max; +} + #ifdef CONFIG_XEN #ifndef __ia64__ @@ -378,49 +450,62 @@ static int unmap_pte_fn(pte_t *pte, stru } #endif -int gnttab_resume(void) +static int gnttab_map(unsigned int start_idx, unsigned int end_idx) { struct gnttab_setup_table setup; - unsigned long frames[NR_GRANT_FRAMES]; + unsigned long *frames; + unsigned int nr_gframes = end_idx + 1; int rc; -#ifndef __ia64__ - void *pframes = frames; - struct vm_struct *area; -#endif + + frames = kmalloc(nr_gframes * sizeof(unsigned long), GFP_ATOMIC); + if (!frames) + return -ENOMEM; setup.dom = DOMID_SELF; - setup.nr_frames = NR_GRANT_FRAMES; + setup.nr_frames = nr_gframes; set_xen_guest_handle(setup.frame_list, frames); rc = HYPERVISOR_grant_table_op(GNTTABOP_setup_table, &setup, 1); - if (rc == -ENOSYS) + if (rc == -ENOSYS) { + kfree(frames); return -ENOSYS; + } BUG_ON(rc || setup.status); #ifndef __ia64__ if (shared == NULL) { - area = get_vm_area(PAGE_SIZE * NR_GRANT_FRAMES, VM_IOREMAP); + struct vm_struct *area; + area = alloc_vm_area(PAGE_SIZE * max_nr_grant_frames()); BUG_ON(area == NULL); shared = area->addr; } rc = apply_to_page_range(&init_mm, (unsigned long)shared, - PAGE_SIZE * NR_GRANT_FRAMES, - map_pte_fn, &pframes); + PAGE_SIZE * nr_gframes, + map_pte_fn, &frames); BUG_ON(rc); + frames -= nr_gframes; /* adjust after map_pte_fn() */ #else shared = __va(frames[0] << PAGE_SHIFT); - printk("grant table at %p\n", shared); #endif - return 0; + kfree(frames); + + return 0; +} + +int gnttab_resume(void) +{ + if (max_nr_grant_frames() < nr_grant_frames) + return -ENOSYS; + return gnttab_map(0, nr_grant_frames - 1); } int gnttab_suspend(void) { #ifndef __ia64__ apply_to_page_range(&init_mm, (unsigned long)shared, - PAGE_SIZE * NR_GRANT_FRAMES, + PAGE_SIZE * nr_grant_frames, unmap_pte_fn, NULL); #endif return 0; @@ -430,24 +515,39 @@ int gnttab_suspend(void) #include <platform-pci.h> -int gnttab_resume(void) -{ - unsigned long frames; +static int gnttab_map(unsigned int start_idx, unsigned int end_idx) +{ struct xen_add_to_physmap xatp; unsigned int i; - frames = alloc_xen_mmio(PAGE_SIZE * NR_GRANT_FRAMES); - - for (i = 0; i < NR_GRANT_FRAMES; i++) { + /* Loop backwards, so that the first hypercall has the largest index, + * ensuring that the table will grow only once. + */ + for (i = end_idx; i >= start_idx; i--) { xatp.domid = DOMID_SELF; xatp.idx = i; xatp.space = XENMAPSPACE_grant_table; - xatp.gpfn = (frames >> PAGE_SHIFT) + i; + xatp.gpfn = (resume_frames >> PAGE_SHIFT) + i; if (HYPERVISOR_memory_op(XENMEM_add_to_physmap, &xatp)) BUG(); } - - shared = ioremap(frames, PAGE_SIZE * NR_GRANT_FRAMES); +} + +int gnttab_resume(void) +{ + struct xen_add_to_physmap xatp; + unsigned int i, max_nr_gframes, nr_gframes; + + nr_gframes = nr_grant_frames; + max_nr_gframes = max_nr_grant_frames(); + if (max_nr_gframes < nr_gframes) + return -ENOSYS; + + resume_frames = alloc_xen_mmio(PAGE_SIZE * max_nr_gframes); + + gnttab_map(0, nr_gframes - 1); + + shared = ioremap(resume_frames, PAGE_SIZE * max_nr_gframes); if (shared == NULL) { printk("error to ioremap gnttab share frames\n"); return -1; @@ -459,28 +559,79 @@ int gnttab_suspend(void) int gnttab_suspend(void) { iounmap(shared); + resume_frames = 0; return 0; } #endif /* !CONFIG_XEN */ +static int gnttab_expand(unsigned int req_entries) +{ + int rc; + unsigned int cur, extra; + + cur = nr_grant_frames; + extra = ((req_entries + (GREFS_PER_GRANT_FRAME-1)) / + GREFS_PER_GRANT_FRAME); + if (cur + extra > max_nr_grant_frames()) + return -ENOSPC; + + if ((rc = gnttab_map(cur, cur + extra - 1)) == 0) + rc = grow_gnttab_list(extra); + + return rc; +} + int __devinit gnttab_init(void) { int i; + unsigned int max_nr_glist_frames; + unsigned int nr_init_grefs; if (!is_running_on_xen()) return -ENODEV; + nr_grant_frames = 1; + boot_max_nr_grant_frames = __max_nr_grant_frames(); + + /* Determine the maximum number of frames required for the + * grant reference free list on the current hypervisor. + */ + max_nr_glist_frames = (boot_max_nr_grant_frames * + GREFS_PER_GRANT_FRAME / + (PAGE_SIZE / sizeof(grant_ref_t))); + + gnttab_list = kmalloc(max_nr_glist_frames * sizeof(grant_ref_t *), + GFP_KERNEL); + if (gnttab_list == NULL) + return -ENOMEM; + + for (i = 0; i < nr_grant_frames; i++) { + gnttab_list[i] = (grant_ref_t *)__get_free_page(GFP_KERNEL); + if (gnttab_list[i] == NULL) + goto ini_nomem; + } + if (gnttab_resume() < 0) return -ENODEV; - for (i = NR_RESERVED_ENTRIES; i < NR_GRANT_ENTRIES; i++) - gnttab_list[i] = i + 1; - gnttab_free_count = NR_GRANT_ENTRIES - NR_RESERVED_ENTRIES; + nr_init_grefs = nr_grant_frames * GREFS_PER_GRANT_FRAME; + + for (i = NR_RESERVED_ENTRIES; i < nr_init_grefs - 1; i++) + gnttab_entry(i) = i + 1; + + gnttab_entry(nr_init_grefs - 1) = GNTTAB_LIST_END; + gnttab_free_count = nr_init_grefs - NR_RESERVED_ENTRIES; gnttab_free_head = NR_RESERVED_ENTRIES; printk("Grant table initialized\n"); return 0; + + ini_nomem: + for (i--; i >= 0; i--) + free_page((unsigned long)gnttab_list[i]); + kfree(gnttab_list); + return -ENOMEM; } #ifdef CONFIG_XEN diff -r 04c23c1ef888 -r d907467f08cd linux-2.6-xen-sparse/drivers/xen/core/smpboot.c --- a/linux-2.6-xen-sparse/drivers/xen/core/smpboot.c Sun Feb 18 16:13:13 2007 -0700 +++ b/linux-2.6-xen-sparse/drivers/xen/core/smpboot.c Tue Feb 20 12:58:22 2007 -0700 @@ -349,8 +349,7 @@ void __init smp_prepare_cpus(unsigned in void __devinit smp_prepare_boot_cpu(void) { - cpu_present_map = cpumask_of_cpu(0); - cpu_online_map = cpumask_of_cpu(0); + prefill_possible_map(); } #ifdef CONFIG_HOTPLUG_CPU diff -r 04c23c1ef888 -r d907467f08cd linux-2.6-xen-sparse/drivers/xen/netback/interface.c --- a/linux-2.6-xen-sparse/drivers/xen/netback/interface.c Sun Feb 18 16:13:13 2007 -0700 +++ b/linux-2.6-xen-sparse/drivers/xen/netback/interface.c Tue Feb 20 12:58:22 2007 -0700 @@ -194,15 +194,12 @@ static int map_frontend_pages( netif_t *netif, grant_ref_t tx_ring_ref, grant_ref_t rx_ring_ref) { struct gnttab_map_grant_ref op; - int ret; gnttab_set_map_op(&op, (unsigned long)netif->tx_comms_area->addr, GNTMAP_host_map, tx_ring_ref, netif->domid); - lock_vm_area(netif->tx_comms_area); - ret = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1); - unlock_vm_area(netif->tx_comms_area); - BUG_ON(ret); + if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1)) + BUG(); if (op.status) { DPRINTK(" Gnttab failure mapping tx_ring_ref!\n"); @@ -215,10 +212,8 @@ static int map_frontend_pages( gnttab_set_map_op(&op, (unsigned long)netif->rx_comms_area->addr, GNTMAP_host_map, rx_ring_ref, netif->domid); - lock_vm_area(netif->rx_comms_area); - ret = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1); - unlock_vm_area(netif->rx_comms_area); - BUG_ON(ret); + if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1)) + BUG(); if (op.status) { DPRINTK(" Gnttab failure mapping rx_ring_ref!\n"); @@ -234,23 +229,18 @@ static void unmap_frontend_pages(netif_t static void unmap_frontend_pages(netif_t *netif) { struct gnttab_unmap_grant_ref op; - int ret; gnttab_set_unmap_op(&op, (unsigned long)netif->tx_comms_area->addr, GNTMAP_host_map, netif->tx_shmem_handle); - lock_vm_area(netif->tx_comms_area); - ret = HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1); - unlock_vm_area(netif->tx_comms_area); - BUG_ON(ret); + if (HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1)) + BUG(); gnttab_set_unmap_op(&op, (unsigned long)netif->rx_comms_area->addr, GNTMAP_host_map, netif->rx_shmem_handle); - lock_vm_area(netif->rx_comms_area); - ret = HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1); - unlock_vm_area(netif->rx_comms_area); - BUG_ON(ret); + if (HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1)) + BUG(); } int netif_map(netif_t *netif, unsigned long tx_ring_ref, diff -r 04c23c1ef888 -r d907467f08cd linux-2.6-xen-sparse/drivers/xen/tpmback/interface.c --- a/linux-2.6-xen-sparse/drivers/xen/tpmback/interface.c Sun Feb 18 16:13:13 2007 -0700 +++ b/linux-2.6-xen-sparse/drivers/xen/tpmback/interface.c Tue Feb 20 12:58:22 2007 -0700 @@ -79,16 +79,13 @@ tpmif_t *tpmif_find(domid_t domid, struc static int map_frontend_page(tpmif_t *tpmif, unsigned long shared_page) { - int ret; struct gnttab_map_grant_ref op; gnttab_set_map_op(&op, (unsigned long)tpmif->tx_area->addr, GNTMAP_host_map, shared_page, tpmif->domid); - lock_vm_area(tpmif->tx_area); - ret = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1); - unlock_vm_area(tpmif->tx_area); - BUG_ON(ret); + if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1)) + BUG(); if (op.status) { DPRINTK(" Grant table operation failure !\n"); @@ -104,15 +101,12 @@ static void unmap_frontend_page(tpmif_t static void unmap_frontend_page(tpmif_t *tpmif) { struct gnttab_unmap_grant_ref op; - int ret; gnttab_set_unmap_op(&op, (unsigned long)tpmif->tx_area->addr, GNTMAP_host_map, tpmif->shmem_handle); - lock_vm_area(tpmif->tx_area); - ret = HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1); - unlock_vm_area(tpmif->tx_area); - BUG_ON(ret); + if (HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1)) + BUG(); } int tpmif_map(tpmif_t *tpmif, unsigned long shared_page, unsigned int evtchn) diff -r 04c23c1ef888 -r d907467f08cd linux-2.6-xen-sparse/drivers/xen/util.c --- a/linux-2.6-xen-sparse/drivers/xen/util.c Sun Feb 18 16:13:13 2007 -0700 +++ b/linux-2.6-xen-sparse/drivers/xen/util.c Tue Feb 20 12:58:22 2007 -0700 @@ -30,6 +30,11 @@ struct vm_struct *alloc_vm_area(unsigned return NULL; } + /* Map page directories into every address space. */ +#ifdef CONFIG_X86 + vmalloc_sync_all(); +#endif + return area; } EXPORT_SYMBOL_GPL(alloc_vm_area); @@ -42,29 +47,3 @@ void free_vm_area(struct vm_struct *area kfree(area); } EXPORT_SYMBOL_GPL(free_vm_area); - -void lock_vm_area(struct vm_struct *area) -{ - unsigned long i; - char c; - - /* - * Prevent context switch to a lazy mm that doesn't have this area - * mapped into its page tables. - */ - preempt_disable(); - - /* - * Ensure that the page tables are mapped into the current mm. The - * page-fault path will copy the page directory pointers from init_mm. - */ - for (i = 0; i < area->size; i += PAGE_SIZE) - (void)__get_user(c, (char __user *)area->addr + i); -} -EXPORT_SYMBOL_GPL(lock_vm_area); - -void unlock_vm_area(struct vm_struct *area) -{ - preempt_enable(); -} -EXPORT_SYMBOL_GPL(unlock_vm_area); diff -r 04c23c1ef888 -r d907467f08cd linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_backend_client.c --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_backend_client.c Sun Feb 18 16:13:13 2007 -0700 +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_backend_client.c Tue Feb 20 12:58:22 2007 -0700 @@ -48,9 +48,8 @@ struct vm_struct *xenbus_map_ring_valloc gnttab_set_map_op(&op, (unsigned long)area->addr, GNTMAP_host_map, gnt_ref, dev->otherend_id); - lock_vm_area(area); - BUG_ON(HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1)); - unlock_vm_area(area); + if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1)) + BUG(); if (op.status != GNTST_okay) { free_vm_area(area); @@ -76,7 +75,8 @@ int xenbus_map_ring(struct xenbus_device gnttab_set_map_op(&op, (unsigned long)vaddr, GNTMAP_host_map, gnt_ref, dev->otherend_id); - BUG_ON(HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1)); + if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1)) + BUG(); if (op.status != GNTST_okay) { xenbus_dev_fatal(dev, op.status, @@ -98,9 +98,8 @@ int xenbus_unmap_ring_vfree(struct xenbu gnttab_set_unmap_op(&op, (unsigned long)area->addr, GNTMAP_host_map, (grant_handle_t)area->phys_addr); - lock_vm_area(area); - BUG_ON(HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1)); - unlock_vm_area(area); + if (HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1)) + BUG(); if (op.status == GNTST_okay) free_vm_area(area); @@ -121,7 +120,8 @@ int xenbus_unmap_ring(struct xenbus_devi gnttab_set_unmap_op(&op, (unsigned long)vaddr, GNTMAP_host_map, handle); - BUG_ON(HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1)); + if (HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1)) + BUG(); if (op.status != GNTST_okay) xenbus_dev_error(dev, op.status, diff -r 04c23c1ef888 -r d907467f08cd linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypervisor.h --- a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypervisor.h Sun Feb 18 16:13:13 2007 -0700 +++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypervisor.h Tue Feb 20 12:58:22 2007 -0700 @@ -56,6 +56,9 @@ extern shared_info_t *HYPERVISOR_shared_info; +#define vcpu_info(cpu) (HYPERVISOR_shared_info->vcpu_info + (cpu)) +#define current_vcpu_info() vcpu_info(smp_processor_id()) + #ifdef CONFIG_X86_32 extern unsigned long hypervisor_virt_start; #endif diff -r 04c23c1ef888 -r d907467f08cd linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/irqflags.h --- a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/irqflags.h Sun Feb 18 16:13:13 2007 -0700 +++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/irqflags.h Tue Feb 20 12:58:22 2007 -0700 @@ -12,12 +12,6 @@ #ifndef __ASSEMBLY__ -#ifdef CONFIG_SMP -#define __vcpu_id smp_processor_id() -#else -#define __vcpu_id 0 -#endif - /* * The use of 'barrier' in the following reflects their use as local-lock * operations. Reentrancy must be prevented (e.g., __cli()) /before/ following @@ -26,8 +20,7 @@ * includes these barriers, for example. */ -#define __raw_local_save_flags() \ - (&HYPERVISOR_shared_info->vcpu_info[__vcpu_id])->evtchn_upcall_mask; +#define __raw_local_save_flags() (current_vcpu_info()->evtchn_upcall_mask) #define raw_local_save_flags(flags) \ do { (flags) = __raw_local_save_flags(); } while (0) @@ -36,7 +29,7 @@ do { \ do { \ vcpu_info_t *_vcpu; \ barrier(); \ - _vcpu = &HYPERVISOR_shared_info->vcpu_info[__vcpu_id]; \ + _vcpu = current_vcpu_info(); \ if ((_vcpu->evtchn_upcall_mask = (x)) == 0) { \ barrier(); /* unmask then check (avoid races) */ \ if (unlikely(_vcpu->evtchn_upcall_pending)) \ @@ -46,9 +39,7 @@ do { \ #define raw_local_irq_disable() \ do { \ - vcpu_info_t *_vcpu; \ - _vcpu = &HYPERVISOR_shared_info->vcpu_info[__vcpu_id]; \ - _vcpu->evtchn_upcall_mask = 1; \ + current_vcpu_info()->evtchn_upcall_mask = 1; \ barrier(); \ } while (0) @@ -56,7 +47,7 @@ do { \ do { \ vcpu_info_t *_vcpu; \ barrier(); \ - _vcpu = &HYPERVISOR_shared_info->vcpu_info[__vcpu_id]; \ + _vcpu = current_vcpu_info(); \ _vcpu->evtchn_upcall_mask = 0; \ barrier(); /* unmask then check (avoid races) */ \ if (unlikely(_vcpu->evtchn_upcall_pending)) \ diff -r 04c23c1ef888 -r d907467f08cd linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/maddr.h --- a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/maddr.h Sun Feb 18 16:13:13 2007 -0700 +++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/maddr.h Tue Feb 20 12:58:22 2007 -0700 @@ -21,6 +21,7 @@ typedef unsigned long maddr_t; #ifdef CONFIG_XEN extern unsigned long *phys_to_machine_mapping; +extern unsigned long max_mapnr; #undef machine_to_phys_mapping extern unsigned long *machine_to_phys_mapping; @@ -30,20 +31,20 @@ static inline unsigned long pfn_to_mfn(u { if (xen_feature(XENFEAT_auto_translated_physmap)) return pfn; - return phys_to_machine_mapping[(unsigned int)(pfn)] & - ~FOREIGN_FRAME_BIT; + BUG_ON(max_mapnr && pfn >= max_mapnr); + return phys_to_machine_mapping[pfn] & ~FOREIGN_FRAME_BIT; } static inline int phys_to_machine_mapping_valid(unsigned long pfn) { if (xen_feature(XENFEAT_auto_translated_physmap)) return 1; + BUG_ON(max_mapnr && pfn >= max_mapnr); return (phys_to_machine_mapping[pfn] != INVALID_P2M_ENTRY); } static inline unsigned long mfn_to_pfn(unsigned long mfn) { - extern unsigned long max_mapnr; unsigned long pfn; if (xen_feature(XENFEAT_auto_translated_physmap)) @@ -92,7 +93,6 @@ static inline unsigned long mfn_to_pfn(u */ static inline unsigned long mfn_to_local_pfn(unsigned long mfn) { - extern unsigned long max_mapnr; unsigned long pfn = mfn_to_pfn(mfn); if ((pfn < max_mapnr) && !xen_feature(XENFEAT_auto_translated_physmap) @@ -103,6 +103,7 @@ static inline unsigned long mfn_to_local static inline void set_phys_to_machine(unsigned long pfn, unsigned long mfn) { + BUG_ON(max_mapnr && pfn >= max_mapnr); if (xen_feature(XENFEAT_auto_translated_physmap)) { BUG_ON(pfn != mfn && mfn != INVALID_P2M_ENTRY); return; @@ -124,6 +125,20 @@ static inline paddr_t machine_to_phys(ma return phys; } +#ifdef CONFIG_X86_PAE +static inline paddr_t pte_phys_to_machine(paddr_t phys) +{ + /* + * In PAE mode, the NX bit needs to be dealt with in the value + * passed to pfn_to_mfn(). On x86_64, we need to mask it off, + * but for i386 the conversion to ulong for the argument will + * clip it off. + */ + maddr_t machine = pfn_to_mfn(phys >> PAGE_SHIFT); + machine = (machine << PAGE_SHIFT) | (phys & ~PHYSICAL_PAGE_MASK); + return machine; +} + static inline paddr_t pte_machine_to_phys(maddr_t machine) { /* @@ -136,6 +151,7 @@ static inline paddr_t pte_machine_to_phy phys = (phys << PAGE_SHIFT) | (machine & ~PHYSICAL_PAGE_MASK); return phys; } +#endif #else /* !CONFIG_XEN */ @@ -146,7 +162,6 @@ static inline paddr_t pte_machine_to_phy #define phys_to_machine_mapping_valid(pfn) (1) #define phys_to_machine(phys) ((maddr_t)(phys)) #define machine_to_phys(mach) ((paddr_t)(mach)) -#define pte_machine_to_phys(mach) ((paddr_t)(mach)) #endif /* !CONFIG_XEN */ diff -r 04c23c1ef888 -r d907467f08cd linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/page.h --- a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/page.h Sun Feb 18 16:13:13 2007 -0700 +++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/page.h Tue Feb 20 12:58:22 2007 -0700 @@ -28,6 +28,13 @@ #include <asm/bug.h> #include <xen/interface/xen.h> #include <xen/features.h> + +/* + * Need to repeat this here in order to not include pgtable.h (which in turn + * depends on definitions made here), but to be able to use the symbolic + * below. The preprocessor will warn if the two definitions aren't identical. + */ +#define _PAGE_PRESENT 0x001 #define arch_free_page(_page,_order) \ ({ int foreign = PageForeign(_page); \ @@ -81,39 +88,37 @@ typedef struct { unsigned long long pgpr #define pgprot_val(x) ((x).pgprot) #include <asm/maddr.h> #define __pte(x) ({ unsigned long long _x = (x); \ - if (_x & 1) _x = phys_to_machine(_x); \ + if (_x & _PAGE_PRESENT) _x = pte_phys_to_machine(_x); \ ((pte_t) {(unsigned long)(_x), (unsigned long)(_x>>32)}); }) #define __pgd(x) ({ unsigned long long _x = (x); \ - (((_x)&1) ? ((pgd_t) {phys_to_machine(_x)}) : ((pgd_t) {(_x)})); }) + (pgd_t) {((_x) & _PAGE_PRESENT) ? pte_phys_to_machine(_x) : (_x)}; }) #define __pmd(x) ({ unsigned long long _x = (x); \ - (((_x)&1) ? ((pmd_t) {phys_to_machine(_x)}) : ((pmd_t) {(_x)})); }) + (pmd_t) {((_x) & _PAGE_PRESENT) ? pte_phys_to_machine(_x) : (_x)}; }) +static inline unsigned long long pte_val_ma(pte_t x) +{ + return ((unsigned long long)x.pte_high << 32) | x.pte_low; +} static inline unsigned long long pte_val(pte_t x) { - unsigned long long ret; - - if (x.pte_low) { - ret = x.pte_low | (unsigned long long)x.pte_high << 32; - ret = pte_machine_to_phys(ret) | 1; - } else { - ret = 0; - } + unsigned long long ret = pte_val_ma(x); + if (x.pte_low & _PAGE_PRESENT) ret = pte_machine_to_phys(ret); return ret; } static inline unsigned long long pmd_val(pmd_t x) { unsigned long long ret = x.pmd; - if (ret) ret = pte_machine_to_phys(ret) | 1; +#ifdef CONFIG_XEN_COMPAT_030002 + if (ret) ret = pte_machine_to_phys(ret) | _PAGE_PRESENT; +#else + if (ret & _PAGE_PRESENT) ret = pte_machine_to_phys(ret); +#endif return ret; } static inline unsigned long long pgd_val(pgd_t x) { unsigned long long ret = x.pgd; - if (ret) ret = pte_machine_to_phys(ret) | 1; - return ret; -} -static inline unsigned long long pte_val_ma(pte_t x) -{ - return (unsigned long long)x.pte_high << 32 | x.pte_low; + if (ret & _PAGE_PRESENT) ret = pte_machine_to_phys(ret); + return ret; } #define HPAGE_SHIFT 21 #else @@ -123,23 +128,23 @@ typedef struct { unsigned long pgprot; } #define pgprot_val(x) ((x).pgprot) #include <asm/maddr.h> #define boot_pte_t pte_t /* or would you rather have a typedef */ -#define pte_val(x) (((x).pte_low & 1) ? \ - pte_machine_to_phys((x).pte_low) : \ +#define pte_val(x) (((x).pte_low & _PAGE_PRESENT) ? \ + machine_to_phys((x).pte_low) : \ (x).pte_low) #define pte_val_ma(x) ((x).pte_low) #define __pte(x) ({ unsigned long _x = (x); \ - (((_x)&1) ? ((pte_t) {phys_to_machine(_x)}) : ((pte_t) {(_x)})); }) + (pte_t) {((_x) & _PAGE_PRESENT) ? phys_to_machine(_x) : (_x)}; }) #define __pgd(x) ({ unsigned long _x = (x); \ - (((_x)&1) ? ((pgd_t) {phys_to_machine(_x)}) : ((pgd_t) {(_x)})); }) + (pgd_t) {((_x) & _PAGE_PRESENT) ? phys_to_machine(_x) : (_x)}; }) static inline unsigned long pgd_val(pgd_t x) { unsigned long ret = x.pgd; - if (ret) ret = pte_machine_to_phys(ret) | 1; + if (ret & _PAGE_PRESENT) ret = machine_to_phys(ret); return ret; } #define HPAGE_SHIFT 22 #endif -#define PTE_MASK PAGE_MASK +#define PTE_MASK PHYSICAL_PAGE_MASK #ifdef CONFIG_HUGETLB_PAGE #define HPAGE_SIZE ((1UL) << HPAGE_SHIFT) diff -r 04c23c1ef888 -r d907467f08cd linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/pgtable-2level.h --- a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/pgtable-2level.h Sun Feb 18 16:13:13 2007 -0700 +++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/pgtable-2level.h Tue Feb 20 12:58:22 2007 -0700 @@ -38,8 +38,11 @@ #define ptep_get_and_clear(mm,addr,xp) __pte_ma(xchg(&(xp)->pte_low, 0)) #define pte_same(a, b) ((a).pte_low == (b).pte_low) -#define pte_mfn(_pte) ((_pte).pte_low >> PAGE_SHIFT) -#define pte_pfn(_pte) mfn_to_local_pfn(pte_mfn(_pte)) +#define __pte_mfn(_pte) ((_pte).pte_low >> PAGE_SHIFT) +#define pte_mfn(_pte) ((_pte).pte_low & _PAGE_PRESENT ? \ + __pte_mfn(_pte) : pfn_to_mfn(__pte_mfn(_pte))) +#define pte_pfn(_pte) ((_pte).pte_low & _PAGE_PRESENT ? \ + mfn_to_local_pfn(__pte_mfn(_pte)) : __pte_mfn(_pte)) #define pte_page(_pte) pfn_to_page(pte_pfn(_pte)) diff -r 04c23c1ef888 -r d907467f08cd linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/pgtable-3level.h --- a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/pgtable-3level.h Sun Feb 18 16:13:13 2007 -0700 +++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/pgtable-3level.h Tue Feb 20 12:58:22 2007 -0700 @@ -52,22 +52,14 @@ static inline int pte_exec_kernel(pte_t */ #define __HAVE_ARCH_SET_PTE_ATOMIC -#if 1 -/* use writable pagetables */ static inline void set_pte(pte_t *ptep, pte_t pte) { ptep->pte_high = pte.pte_high; smp_wmb(); ptep->pte_low = pte.pte_low; } -# define set_pte_atomic(pteptr,pteval) \ +#define set_pte_atomic(pteptr,pteval) \ set_64bit((unsigned long long *)(pteptr),pte_val_ma(pteval)) -#else -/* no writable pagetables */ -# define set_pte(pteptr,pteval) \ - xen_l1_entry_update((pteptr), (pteval)) -# define set_pte_atomic(pteptr,pteval) set_pte(pteptr,pteval) -#endif #define set_pte_at(_mm,addr,ptep,pteval) do { \ if (((_mm) != current->mm && (_mm) != &init_mm) || \ @@ -145,21 +137,24 @@ static inline int pte_none(pte_t pte) return !pte.pte_low && !pte.pte_high; } -#define pte_mfn(_pte) (((_pte).pte_low >> PAGE_SHIFT) |\ - (((_pte).pte_high & 0xfff) << (32-PAGE_SHIFT))) -#define pte_pfn(_pte) mfn_to_local_pfn(pte_mfn(_pte)) +#define __pte_mfn(_pte) (((_pte).pte_low >> PAGE_SHIFT) | \ + ((_pte).pte_high << (32-PAGE_SHIFT))) +#define pte_mfn(_pte) ((_pte).pte_low & _PAGE_PRESENT ? \ + __pte_mfn(_pte) : pfn_to_mfn(__pte_mfn(_pte))) +#define pte_pfn(_pte) ((_pte).pte_low & _PAGE_PRESENT ? \ + mfn_to_local_pfn(__pte_mfn(_pte)) : __pte_mfn(_pte)) extern unsigned long long __supported_pte_mask; static inline pte_t pfn_pte(unsigned long page_nr, pgprot_t pgprot) { - return pfn_pte_ma(pfn_to_mfn(page_nr), pgprot); + return __pte((((unsigned long long)page_nr << PAGE_SHIFT) | + pgprot_val(pgprot)) & __supported_pte_mask); } static inline pmd_t pfn_pmd(unsigned long page_nr, pgprot_t pgprot) { - BUG(); panic("needs review"); - return __pmd((((unsigned long long)page_nr << PAGE_SHIFT) | \ + return __pmd((((unsigned long long)page_nr << PAGE_SHIFT) | pgprot_val(pgprot)) & __supported_pte_mask); } @@ -180,6 +175,6 @@ static inline pmd_t pfn_pmd(unsigned lon #define __pmd_free_tlb(tlb, x) do { } while (0) -#define vmalloc_sync_all() ((void)0) +void vmalloc_sync_all(void); #endif /* _I386_PGTABLE_3LEVEL_H */ diff -r 04c23c1ef888 -r d907467f08cd linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/pgtable.h --- a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/pgtable.h Sun Feb 18 16:13:13 2007 -0700 +++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/pgtable.h Tue Feb 20 12:58:22 2007 -0700 @@ -315,18 +315,19 @@ static inline void clone_pgd_range(pgd_t static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) { - pte.pte_low &= _PAGE_CHG_MASK; - pte.pte_low |= pgprot_val(newprot); + /* + * Since this might change the present bit (which controls whether + * a pte_t object has undergone p2m translation), we must use + * pte_val() on the input pte and __pte() for the return value. + */ + paddr_t pteval = pte_val(pte); + + pteval &= _PAGE_CHG_MASK; + pteval |= pgprot_val(newprot); #ifdef CONFIG_X86_PAE - /* - * Chop off the NX bit (if present), and add the NX portion of - * the newprot (if present): - */ - pte.pte_high &= ~(1 << (_PAGE_BIT_NX - 32)); - pte.pte_high |= (pgprot_val(newprot) >> 32) & \ - (__supported_pte_mask >> 32); -#endif - return pte; + pteval &= __supported_pte_mask; +#endif + return __pte(pteval); } #define pmd_large(pmd) \ @@ -432,12 +433,15 @@ extern void noexec_setup(const char *str #define ptep_set_access_flags(__vma, __address, __ptep, __entry, __dirty) \ do { \ if (__dirty) { \ - if ( likely((__vma)->vm_mm == current->mm) ) { \ - BUG_ON(HYPERVISOR_update_va_mapping((__address), (__entry), UVMF_INVLPG|UVMF_MULTI|(unsigned long)((__vma)->vm_mm->cpu_vm_mask.bits))); \ - } else { \ - xen_l1_entry_update((__ptep), (__entry)); \ - flush_tlb_page((__vma), (__address)); \ - } \ + if ( likely((__vma)->vm_mm == current->mm) ) { \ + BUG_ON(HYPERVISOR_update_va_mapping(__address, \ + __entry, \ + (unsigned long)(__vma)->vm_mm->cpu_vm_mask.bits| \ + UVMF_INVLPG|UVMF_MULTI)); \ + } else { \ + xen_l1_entry_update(__ptep, __entry); \ + flush_tlb_page(__vma, __address); \ + } \ } \ } while (0) diff -r 04c23c1ef888 -r d907467f08cd linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/system.h --- a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/system.h Sun Feb 18 16:13:13 2007 -0700 +++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/system.h Tue Feb 20 12:58:22 2007 -0700 @@ -100,8 +100,7 @@ __asm__ __volatile__ ("movw %%dx,%1\n\t" #define write_cr0(x) \ __asm__ __volatile__("movl %0,%%cr0": :"r" (x)) -#define read_cr2() \ - (HYPERVISOR_shared_info->vcpu_info[smp_processor_id()].arch.cr2) +#define read_cr2() (current_vcpu_info()->arch.cr2) #define write_cr2(x) \ __asm__ __volatile__("movl %0,%%cr2": :"r" (x)) diff -r 04c23c1ef888 -r d907467f08cd linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/irqflags.h --- a/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/irqflags.h Sun Feb 18 16:13:13 2007 -0700 +++ b/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/irqflags.h Tue Feb 20 12:58:22 2007 -0700 @@ -15,12 +15,6 @@ * Interrupt control: */ -#ifdef CONFIG_SMP -#define __vcpu_id smp_processor_id() -#else -#define __vcpu_id 0 -#endif - /* * The use of 'barrier' in the following reflects their use as local-lock * operations. Reentrancy must be prevented (e.g., __cli()) /before/ following @@ -29,8 +23,7 @@ * includes these barriers, for example. */ -#define __raw_local_save_flags() \ - (&HYPERVISOR_shared_info->vcpu_info[__vcpu_id])->evtchn_upcall_mask; +#define __raw_local_save_flags() (current_vcpu_info()->evtchn_upcall_mask) #define raw_local_save_flags(flags) \ do { (flags) = __raw_local_save_flags(); } while (0) @@ -39,7 +32,7 @@ do { \ do { \ vcpu_info_t *_vcpu; \ barrier(); \ - _vcpu = &HYPERVISOR_shared_info->vcpu_info[__vcpu_id]; \ + _vcpu = current_vcpu_info(); \ if ((_vcpu->evtchn_upcall_mask = (x)) == 0) { \ barrier(); /* unmask then check (avoid races) */ \ if ( unlikely(_vcpu->evtchn_upcall_pending) ) \ @@ -76,9 +69,7 @@ static inline int raw_irqs_disabled_flag #define raw_local_irq_disable() \ do { \ - vcpu_info_t *_vcpu; \ - _vcpu = &HYPERVISOR_shared_info->vcpu_info[__vcpu_id]; \ - _vcpu->evtchn_upcall_mask = 1; \ + current_vcpu_info()->evtchn_upcall_mask = 1; \ barrier(); \ } while (0) @@ -86,7 +77,7 @@ do { \ do { \ vcpu_info_t *_vcpu; \ barrier(); \ - _vcpu = &HYPERVISOR_shared_info->vcpu_info[__vcpu_id]; \ + _vcpu = current_vcpu_info(); \ _vcpu->evtchn_upcall_mask = 0; \ barrier(); /* unmask then check (avoid races) */ \ if ( unlikely(_vcpu->evtchn_upcall_pending) ) \ diff -r 04c23c1ef888 -r d907467f08cd linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/maddr.h --- a/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/maddr.h Sun Feb 18 16:13:13 2007 -0700 +++ b/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/maddr.h Tue Feb 20 12:58:22 2007 -0700 @@ -25,14 +25,15 @@ static inline unsigned long pfn_to_mfn(u { if (xen_feature(XENFEAT_auto_translated_physmap)) return pfn; - return phys_to_machine_mapping[(unsigned int)(pfn)] & - ~FOREIGN_FRAME_BIT; + BUG_ON(end_pfn && pfn >= end_pfn); + return phys_to_machine_mapping[pfn] & ~FOREIGN_FRAME_BIT; } static inline int phys_to_machine_mapping_valid(unsigned long pfn) { if (xen_feature(XENFEAT_auto_translated_physmap)) return 1; + BUG_ON(end_pfn && pfn >= end_pfn); return (phys_to_machine_mapping[pfn] != INVALID_P2M_ENTRY); } @@ -96,6 +97,7 @@ static inline unsigned long mfn_to_local static inline void set_phys_to_machine(unsigned long pfn, unsigned long mfn) { + BUG_ON(end_pfn && pfn >= end_pfn); if (xen_feature(XENFEAT_auto_translated_physmap)) { BUG_ON(pfn != mfn && mfn != INVALID_P2M_ENTRY); return; @@ -117,6 +119,14 @@ static inline paddr_t machine_to_phys(ma return phys; } +static inline paddr_t pte_phys_to_machine(paddr_t phys) +{ + maddr_t machine; + machine = pfn_to_mfn((phys & PHYSICAL_PAGE_MASK) >> PAGE_SHIFT); + machine = (machine << PAGE_SHIFT) | (phys & ~PHYSICAL_PAGE_MASK); + return machine; +} + static inline paddr_t pte_machine_to_phys(maddr_t machine) { paddr_t phys; @@ -134,7 +144,6 @@ static inline paddr_t pte_machine_to_phy #define phys_to_machine_mapping_valid(pfn) (1) #define phys_to_machine(phys) ((maddr_t)(phys)) #define machine_to_phys(mach) ((paddr_t)(mach)) -#define pte_machine_to_phys(mach) ((paddr_t)(mach)) #endif /* !CONFIG_XEN */ diff -r 04c23c1ef888 -r d907467f08cd linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/page.h --- a/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/page.h Sun Feb 18 16:13:13 2007 -0700 +++ b/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/page.h Tue Feb 20 12:58:22 2007 -0700 @@ -8,6 +8,13 @@ #include <asm/bug.h> #endif #include <xen/interface/xen.h> + +/* + * Need to repeat this here in order to not include pgtable.h (which in turn + * depends on definitions made here), but to be able to use the symbolic + * below. The preprocessor will warn if the two definitions aren't identical. + */ +#define _PAGE_PRESENT 0x001 #define arch_free_page(_page,_order) \ ({ int foreign = PageForeign(_page); \ @@ -95,28 +102,33 @@ typedef struct { unsigned long pgd; } pg typedef struct { unsigned long pgprot; } pgprot_t; -#define pte_val(x) (((x).pte & 1) ? pte_machine_to_phys((x).pte) : \ +#define pte_val(x) (((x).pte & _PAGE_PRESENT) ? \ + pte_machine_to_phys((x).pte) : \ (x).pte) #define pte_val_ma(x) ((x).pte) static inline unsigned long pmd_val(pmd_t x) { unsigned long ret = x.pmd; - if (ret) ret = pte_machine_to_phys(ret); +#ifdef CONFIG_XEN_COMPAT_030002 + if (ret) ret = pte_machine_to_phys(ret) | _PAGE_PRESENT; +#else + if (ret & _PAGE_PRESENT) ret = pte_machine_to_phys(ret); +#endif return ret; } static inline unsigned long pud_val(pud_t x) { unsigned long ret = x.pud; - if (ret) ret = pte_machine_to_phys(ret); + if (ret & _PAGE_PRESENT) ret = pte_machine_to_phys(ret); return ret; } static inline unsigned long pgd_val(pgd_t x) { unsigned long ret = x.pgd; - if (ret) ret = pte_machine_to_phys(ret); + if (ret & _PAGE_PRESENT) ret = pte_machine_to_phys(ret); return ret; } @@ -124,25 +136,25 @@ static inline unsigned long pgd_val(pgd_ static inline pte_t __pte(unsigned long x) { - if (x & 1) x = phys_to_machine(x); + if (x & _PAGE_PRESENT) x = pte_phys_to_machine(x); return ((pte_t) { (x) }); } static inline pmd_t __pmd(unsigned long x) { - if ((x & 1)) x = phys_to_machine(x); + if (x & _PAGE_PRESENT) x = pte_phys_to_machine(x); return ((pmd_t) { (x) }); } static inline pud_t __pud(unsigned long x) { - if ((x & 1)) x = phys_to_machine(x); + if (x & _PAGE_PRESENT) x = pte_phys_to_machine(x); return ((pud_t) { (x) }); } static inline pgd_t __pgd(unsigned long x) { - if ((x & 1)) x = phys_to_machine(x); + if (x & _PAGE_PRESENT) x = pte_phys_to_machine(x); return ((pgd_t) { (x) }); } diff -r 04c23c1ef888 -r d907467f08cd linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/pgtable.h --- a/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/pgtable.h Sun Feb 18 16:13:13 2007 -0700 +++ b/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/pgtable.h Tue Feb 20 12:58:22 2007 -0700 @@ -302,19 +302,20 @@ static inline unsigned long pud_bad(pud_ #define pages_to_mb(x) ((x) >> (20-PAGE_SHIFT)) -#define pte_mfn(_pte) (((_pte).pte & PTE_MASK) >> PAGE_SHIFT) -#define pte_pfn(_pte) mfn_to_local_pfn(pte_mfn(_pte)) +#define __pte_mfn(_pte) (((_pte).pte & PTE_MASK) >> PAGE_SHIFT) +#define pte_mfn(_pte) ((_pte).pte & _PAGE_PRESENT ? \ + __pte_mfn(_pte) : pfn_to_mfn(__pte_mfn(_pte))) +#define pte_pfn(_pte) ((_pte).pte & _PAGE_PRESENT ? \ + mfn_to_local_pfn(__pte_mfn(_pte)) : __pte_mfn(_pte)) #define pte_page(x) pfn_to_page(pte_pfn(x)) static inline pte_t pfn_pte(unsigned long page_nr, pgprot_t pgprot) { - pte_t pte; - - (pte).pte = (pfn_to_mfn(page_nr) << PAGE_SHIFT); - (pte).pte |= pgprot_val(pgprot); - (pte).pte &= __supported_pte_mask; - return pte; + unsigned long pte = page_nr << PAGE_SHIFT; + pte |= pgprot_val(pgprot); + pte &= __supported_pte_mask; + return __pte(pte); } /* @@ -446,18 +447,25 @@ static inline pud_t *pud_offset_k(pgd_t /* physical address -> PTE */ static inline pte_t mk_pte_phys(unsigned long physpage, pgprot_t pgprot) { - pte_t pte; - (pte).pte = physpage | pgprot_val(pgprot); - return pte; + unsigned long pteval; + pteval = physpage | pgprot_val(pgprot); + return __pte(pteval); } /* Change flags of a PTE */ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) { - (pte).pte &= _PAGE_CHG_MASK; - (pte).pte |= pgprot_val(newprot); - (pte).pte &= __supported_pte_mask; - return pte; + /* + * Since this might change the present bit (which controls whether + * a pte_t object has undergone p2m translation), we must use + * pte_val() on the input pte and __pte() for the return value. + */ + unsigned long pteval = pte_val(pte); + + pteval &= _PAGE_CHG_MASK; + pteval |= pgprot_val(newprot); + pteval &= __supported_pte_mask; + return __pte(pteval); } #define pte_index(address) \ @@ -479,24 +487,18 @@ static inline pte_t pte_modify(pte_t pte * race with other CPU's that might be updating the dirty * bit at the same time. */ #define __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS -#if 0 #define ptep_set_access_flags(__vma, __address, __ptep, __entry, __dirty) \ do { \ if (__dirty) { \ - set_pte(__ptep, __entry); \ - flush_tlb_page(__vma, __address); \ - } \ - } while (0) -#endif -#define ptep_set_access_flags(__vma, __address, __ptep, __entry, __dirty) \ - do { \ - if (__dirty) { \ - if ( likely((__vma)->vm_mm == current->mm) ) { \ - BUG_ON(HYPERVISOR_update_va_mapping((__address), (__entry), UVMF_INVLPG|UVMF_MULTI|(unsigned long)((__vma)->vm_mm->cpu_vm_mask.bits))); \ - } else { \ - xen_l1_entry_update((__ptep), (__entry)); \ - flush_tlb_page((__vma), (__address)); \ - } \ + if ( likely((__vma)->vm_mm == current->mm) ) { \ + BUG_ON(HYPERVISOR_update_va_mapping(__address, \ + __entry, \ + (unsigned long)(__vma)->vm_mm->cpu_vm_mask.bits| \ + UVMF_INVLPG|UVMF_MULTI)); \ + } else { \ + xen_l1_entry_update(__ptep, __entry); \ + flush_tlb_page(__vma, __address); \ + } \ } \ } while (0) diff -r 04c23c1ef888 -r d907467f08cd linux-2.6-xen-sparse/include/linux/pfn.h --- a/linux-2.6-xen-sparse/include/linux/pfn.h Sun Feb 18 16:13:13 2007 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,9 +0,0 @@ -#ifndef _LINUX_PFN_H_ -#define _LINUX_PFN_H_ - -#define PFN_ALIGN(x) (((unsigned long long)(x) + (PAGE_SIZE - 1)) & PAGE_MASK) -#define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT) -#define PFN_DOWN(x) ((x) >> PAGE_SHIFT) -#define PFN_PHYS(x) ((unsigned long long)(x) << PAGE_SHIFT) - -#endif diff -r 04c23c1ef888 -r d907467f08cd linux-2.6-xen-sparse/include/xen/driver_util.h --- a/linux-2.6-xen-sparse/include/xen/driver_util.h Sun Feb 18 16:13:13 2007 -0700 +++ b/linux-2.6-xen-sparse/include/xen/driver_util.h Tue Feb 20 12:58:22 2007 -0700 @@ -9,8 +9,4 @@ extern struct vm_struct *alloc_vm_area(u extern struct vm_struct *alloc_vm_area(unsigned long size); extern void free_vm_area(struct vm_struct *area); -/* Lock an area so that PTEs are accessible in the current address space. */ -extern void lock_vm_area(struct vm_struct *area); -extern void unlock_vm_area(struct vm_struct *area); - #endif /* __ASM_XEN_DRIVER_UTIL_H__ */ diff -r 04c23c1ef888 -r d907467f08cd linux-2.6-xen-sparse/include/xen/gnttab.h --- a/linux-2.6-xen-sparse/include/xen/gnttab.h Sun Feb 18 16:13:13 2007 -0700 +++ b/linux-2.6-xen-sparse/include/xen/gnttab.h Tue Feb 20 12:58:22 2007 -0700 @@ -42,13 +42,6 @@ #include <asm/maddr.h> /* maddr_t */ #include <xen/interface/grant_table.h> #include <xen/features.h> - -/* NR_GRANT_FRAMES must be less than or equal to that configured in Xen */ -#ifdef __ia64__ -#define NR_GRANT_FRAMES 1 -#else -#define NR_GRANT_FRAMES 4 -#endif struct gnttab_free_callback { struct gnttab_free_callback *next; @@ -109,12 +102,6 @@ void gnttab_grant_foreign_transfer_ref(g void gnttab_grant_foreign_transfer_ref(grant_ref_t, domid_t domid, unsigned long pfn); -#ifdef __ia64__ -#define gnttab_map_vaddr(map) __va(map.dev_bus_addr) -#else -#define gnttab_map_vaddr(map) ((void *)(map.host_virt_addr)) -#endif - int gnttab_suspend(void); int gnttab_resume(void); diff -r 04c23c1ef888 -r d907467f08cd patches/linux-2.6.18/x86-elfnote-as-preprocessor-macro.patch --- a/patches/linux-2.6.18/x86-elfnote-as-preprocessor-macro.patch Sun Feb 18 16:13:13 2007 -0700 +++ b/patches/linux-2.6.18/x86-elfnote-as-preprocessor-macro.patch Tue Feb 20 12:58:22 2007 -0700 @@ -1,7 +1,7 @@ diff -pruN ../orig-linux-2.6.18/include/ diff -pruN ../orig-linux-2.6.18/include/linux/elfnote.h ./include/linux/elfnote.h --- ../orig-linux-2.6.18/include/linux/elfnote.h 2007-01-12 18:19:44.000000000 +0000 +++ ./include/linux/elfnote.h 2007-01-12 18:21:02.000000000 +0000 -@@ -31,22 +31,24 @@ +@@ -31,22 +31,38 @@ /* * Generate a structure with the same shape as Elf{32,64}_Nhdr (which * turn out to be the same size and shape), followed by the name and @@ -25,9 +25,21 @@ diff -pruN ../orig-linux-2.6.18/include/ -2:.align 4 -3:\desc -4:.align 4 --.popsection ++#ifdef __STDC__ ++#define ELFNOTE(name, type, desctype, descdata...) \ ++.pushsection .note.name ; \ ++ .align 4 ; \ ++ .long 2f - 1f /* namesz */ ; \ ++ .long 4f - 3f /* descsz */ ; \ ++ .long type ; \ ++1:.asciz #name ; \ ++2:.align 4 ; \ ++3:desctype descdata ; \ ++4:.align 4 ; \ + .popsection -.endm -+#define ELFNOTE(name, type, desctype, descdata) \ ++#else /* !__STDC__, i.e. -traditional */ ++#define ELFNOTE(name, type, desctype, descdata) \ +.pushsection .note.name ; \ + .align 4 ; \ + .long 2f - 1f /* namesz */ ; \ @@ -37,7 +49,8 @@ diff -pruN ../orig-linux-2.6.18/include/ +2:.align 4 ; \ +3:desctype descdata ; \ +4:.align 4 ; \ -+.popsection ; ++.popsection ++#endif /* __STDC__ */ #else /* !__ASSEMBLER__ */ #include <linux/elf.h> /* diff -r 04c23c1ef888 -r d907467f08cd tools/blktap/drivers/Makefile --- a/tools/blktap/drivers/Makefile Sun Feb 18 16:13:13 2007 -0700 +++ b/tools/blktap/drivers/Makefile Tue Feb 20 12:58:22 2007 -0700 @@ -5,7 +5,7 @@ INCLUDES += -I.. -I../lib IBIN = blktapctrl tapdisk QCOW_UTIL = img2qcow qcow2raw qcow-create -INST_DIR = /usr/sbin +INST_DIR = /usr/sbin LIBAIO_DIR = ../../libaio/src CFLAGS += -Werror @@ -17,7 +17,7 @@ CFLAGS += -D_GNU_SOURCE # Get gcc to generate the dependencies for us. CFLAGS += -Wp,-MD,.$(@F).d -DEPS = .*.d +DEPS = .*.d THREADLIB := -lpthread -lz LIBS := -L. -L.. -L../lib @@ -29,10 +29,10 @@ LIBS += -L$(XEN_XENSTORE) -lxenstor AIOLIBS := $(LIBAIO_DIR)/libaio.a -BLK-OBJS := block-aio.o -BLK-OBJS += block-sync.o +BLK-OBJS := block-aio.o +BLK-OBJS += block-sync.o BLK-OBJS += block-vmdk.o -BLK-OBJS += block-ram.o +BLK-OBJS += block-ram.o BLK-OBJS += block-qcow.o BLK-OBJS += aes.o @@ -52,13 +52,13 @@ qcow-util: img2qcow qcow2raw qcow-create qcow-util: img2qcow qcow2raw qcow-create img2qcow qcow2raw qcow-create: %: $(BLK-OBJS) - $(CC) $(CFLAGS) -o $* $(BLK-OBJS) $*.c $(AIOLIBS) $(LIBS) + $(CC) $(CFLAGS) -o $* $(BLK-OBJS) $*.c $(AIOLIBS) $(LIBS) install: all - $(INSTALL_PROG) $(IBIN) $(QCOW_UTIL) $(DESTDIR)$(INST_DIR) + $(INSTALL_PROG) $(IBIN) $(QCOW_UTIL) $(VHD_UTIL) $(DESTDIR)$(INST_DIR) clean: - rm -rf *.o *~ $(DEPS) xen TAGS $(IBIN) $(LIB) $(QCOW_UTIL) + rm -rf *.o *~ $(DEPS) xen TAGS $(IBIN) $(LIB) $(QCOW_UTIL) $(VHD_UTIL) .PHONY: clean install diff -r 04c23c1ef888 -r d907467f08cd tools/blktap/drivers/block-aio.c --- a/tools/blktap/drivers/block-aio.c Sun Feb 18 16:13:13 2007 -0700 +++ b/tools/blktap/drivers/block-aio.c Tue Feb 20 12:58:22 2007 -0700 @@ -58,6 +58,7 @@ struct pending_aio { td_callback_t cb; int id; void *private; + uint64_t lsec; }; struct tdaio_state { @@ -139,12 +140,23 @@ static int get_image_info(struct td_stat return 0; } +static inline void init_fds(struct disk_driver *dd) +{ + int i; + struct tdaio_state *prv = (struct tdaio_state *)dd->private; + + for(i = 0; i < MAX_IOFD; i++) + dd->io_fd[i] = 0; + + dd->io_fd[0] = prv->poll_fd; +} + /* Open the disk file and initialize aio state. */ -int tdaio_open (struct td_state *s, const char *name) +int tdaio_open (struct disk_driver *dd, const char *name) { int i, fd, ret = 0; - struct tdaio_state *prv = (struct tdaio_state *)s->private; - s->private = prv; + struct td_state *s = dd->td_state; + struct tdaio_state *prv = (struct tdaio_state *)dd->private; DPRINTF("block-aio open('%s')", name); /* Initialize AIO */ @@ -194,18 +206,21 @@ int tdaio_open (struct td_state *s, cons prv->fd = fd; + init_fds(dd); ret = get_image_info(s, fd); + done: return ret; } -int tdaio_queue_read(struct td_state *s, uint64_t sector, - int nb_sectors, char *buf, td_callback_t cb, - int id, void *private) +int tdaio_queue_read(struct disk_driver *dd, uint64_t sector, + int nb_sectors, char *buf, td_callback_t cb, + int id, void *private) { struct iocb *io; struct pending_aio *pio; - struct tdaio_state *prv = (struct tdaio_state *)s->private; + struct td_state *s = dd->td_state; + struct tdaio_state *prv = (struct tdaio_state *)dd->private; int size = nb_sectors * s->sector_size; uint64_t offset = sector * (uint64_t)s->sector_size; long ioidx; @@ -219,22 +234,24 @@ int tdaio_queue_read(struct td_state *s, pio->cb = cb; pio->id = id; pio->private = private; + pio->lsec = sector; io_prep_pread(io, prv->fd, buf, size, offset); io->data = (void *)ioidx; prv->iocb_queue[prv->iocb_queued++] = io; - - return 0; -} - -int tdaio_queue_write(struct td_state *s, uint64_t sector, - int nb_sectors, char *buf, td_callback_t cb, - int id, void *private) + + return 0; +} + +int tdaio_queue_write(struct disk_driver *dd, uint64_t sector, + int nb_sectors, char *buf, td_callback_t cb, + int id, void *private) { struct iocb *io; struct pending_aio *pio; - struct tdaio_state *prv = (struct tdaio_state *)s->private; + struct td_state *s = dd->td_state; + struct tdaio_state *prv = (struct tdaio_state *)dd->private; int size = nb_sectors * s->sector_size; uint64_t offset = sector * (uint64_t)s->sector_size; long ioidx; @@ -248,19 +265,20 @@ int tdaio_queue_write(struct td_state *s pio->cb = cb; pio->id = id; pio->private = private; + pio->lsec = sector; io_prep_pwrite(io, prv->fd, buf, size, offset); io->data = (void *)ioidx; prv->iocb_queue[prv->iocb_queued++] = io; - - return 0; -} - -int tdaio_submit(struct td_state *s) + + return 0; +} + +int tdaio_submit(struct disk_driver *dd) { int ret; - struct tdaio_state *prv = (struct tdaio_state *)s->private; + struct tdaio_state *prv = (struct tdaio_state *)dd->private; ret = io_submit(prv->aio_ctx, prv->iocb_queued, prv->iocb_queue); @@ -269,38 +287,24 @@ int tdaio_submit(struct td_state *s) /* Success case: */ prv->iocb_queued = 0; - return ret; -} - -int *tdaio_get_fd(struct td_state *s) -{ - struct tdaio_state *prv = (struct tdaio_state *)s->private; - int *fds, i; - - fds = malloc(sizeof(int) * MAX_IOFD); - /*initialise the FD array*/ - for(i=0;i<MAX_IOFD;i++) fds[i] = 0; - - fds[0] = prv->poll_fd; - - return fds; -} - -int tdaio_close(struct td_state *s) -{ - struct tdaio_state *prv = (struct tdaio_state *)s->private; + return 0; +} + +int tdaio_close(struct disk_driver *dd) +{ + struct tdaio_state *prv = (struct tdaio_state *)dd->private; io_destroy(prv->aio_ctx); close(prv->fd); - - return 0; -} - -int tdaio_do_callbacks(struct td_state *s, int sid) + + return 0; +} + +int tdaio_do_callbacks(struct disk_driver *dd, int sid) { int ret, i, rsp = 0; struct io_event *ep; - struct tdaio_state *prv = (struct tdaio_state *)s->private; + struct tdaio_state *prv = (struct tdaio_state *)dd->private; /* Non-blocking test for completed io. */ ret = io_getevents(prv->aio_ctx, 0, MAX_AIO_REQS, prv->aio_events, @@ -311,22 +315,34 @@ int tdaio_do_callbacks(struct td_state * struct pending_aio *pio; pio = &prv->pending_aio[(long)io->data]; - rsp += pio->cb(s, ep->res == io->u.c.nbytes ? 0 : 1, + rsp += pio->cb(dd, ep->res == io->u.c.nbytes ? 0 : 1, + pio->lsec, io->u.c.nbytes >> 9, pio->id, pio->private); prv->iocb_free[prv->iocb_free_count++] = io; } return rsp; } - + +int tdaio_has_parent(struct disk_driver *dd) +{ + return 0; +} + +int tdaio_get_parent(struct disk_driver *dd, struct disk_driver *parent) +{ + return -EINVAL; +} + struct tap_disk tapdisk_aio = { - "tapdisk_aio", - sizeof(struct tdaio_state), - tdaio_open, - tdaio_queue_read, - tdaio_queue_write, - tdaio_submit, - tdaio_get_fd, - tdaio_close, - tdaio_do_callbacks, + .disk_type = "tapdisk_aio", + .private_data_size = sizeof(struct tdaio_state), + .td_open = tdaio_open, + .td_queue_read = tdaio_queue_read, + .td_queue_write = tdaio_queue_write, + .td_submit = tdaio_submit, + .td_has_parent = tdaio_has_parent, + .td_get_parent = tdaio_get_parent, + .td_close = tdaio_close, + .td_do_callbacks = tdaio_do_callbacks, }; diff -r 04c23c1ef888 -r d907467f08cd tools/blktap/drivers/block-qcow.c --- a/tools/blktap/drivers/block-qcow.c Sun Feb 18 16:13:13 2007 -0700 +++ b/tools/blktap/drivers/block-qcow.c Tue Feb 20 12:58:22 2007 -0700 @@ -55,7 +55,6 @@ /******AIO DEFINES******/ #define REQUEST_ASYNC_FD 1 -#define MAX_QCOW_IDS 0xFFFF #define MAX_AIO_REQS (MAX_REQUESTS * MAX_SEGMENTS_PER_REQ) struct pending_aio { @@ -65,7 +64,6 @@ struct pending_aio { int nb_sectors; char *buf; uint64_t sector; - int qcow_idx; }; #define IOCB_IDX(_s, _io) ((_io) - (_s)->iocb_list) @@ -115,9 +113,9 @@ struct tdqcow_state { struct tdqcow_state { int fd; /*Main Qcow file descriptor */ uint64_t fd_end; /*Store a local record of file length */ - int bfd; /*Backing file descriptor*/ char *name; /*Record of the filename*/ - int poll_pipe[2]; /*dummy fd for polling on */ + uint32_t backing_file_size; + uint64_t backing_file_offset; int encrypted; /*File contents are encrypted or plain*/ int cluster_bits; /*Determines length of cluster as *indicated by file hdr*/ @@ -149,7 +147,6 @@ struct tdqcow_state { AES_KEY aes_decrypt_key; /*AES key*/ /* libaio state */ io_context_t aio_ctx; - int nr_reqs [MAX_QCOW_IDS]; struct iocb iocb_list [MAX_AIO_REQS]; struct iocb *iocb_free [MAX_AIO_REQS]; struct pending_aio pending_aio[MAX_AIO_REQS]; @@ -162,10 +159,11 @@ struct tdqcow_state { static int decompress_cluster(struct tdqcow_state *s, uint64_t cluster_offset); -static int init_aio_state(struct td_state *bs) +static int init_aio_state(struct disk_driver *dd) { int i; - struct tdqcow_state *s = (struct tdqcow_state *)bs->private; + struct td_state *bs = dd->td_state; + struct tdqcow_state *s = (struct tdqcow_state *)dd->private; long ioidx; /*Initialize Locking bitmap*/ @@ -202,8 +200,7 @@ static int init_aio_state(struct td_stat for (i=0;i<MAX_AIO_REQS;i++) s->iocb_free[i] = &s->iocb_list[i]; - for (i=0;i<MAX_QCOW_IDS;i++) - s->nr_reqs[i] = 0; + DPRINTF("AIO state initialised\n"); return 0; @@ -238,7 +235,10 @@ static uint32_t gen_cksum(char *ptr, int if(!md) return 0; - if (MD5((unsigned char *)ptr, len, md) != md) return 0; + if (MD5((unsigned char *)ptr, len, md) != md) { + free(md); + return 0; + } memcpy(&ret, md, sizeof(uint32_t)); free(md); @@ -247,26 +247,42 @@ static uint32_t gen_cksum(char *ptr, int static int get_filesize(char *filename, uint64_t *size, struct stat *st) { - int blockfd; + int fd; + QCowHeader header; /*Set to the backing file size*/ + fd = open(filename, O_RDONLY); + if (fd < 0) + return -1; + if (read(fd, &header, sizeof(header)) < sizeof(header)) { + close(fd); + return -1; + } + close(fd); + + be32_to_cpus(&header.magic); + be64_to_cpus(&header.size); + if (header.magic == QCOW_MAGIC) { + *size = header.size >> SECTOR_SHIFT; + return 0; + } + if(S_ISBLK(st->st_mode)) { - blockfd = open(filename, O_RDONLY); - if (blockfd < 0) + fd = open(filename, O_RDONLY); + if (fd < 0) return -1; - if (ioctl(blockfd,BLKGETSIZE,size)!=0) { + if (ioctl(fd,BLKGETSIZE,size)!=0) { printf("Unable to get Block device size\n"); - close(blockfd); + close(fd); return -1; } - close(blockfd); + close(fd); } else *size = (st->st_size >> SECTOR_SHIFT); return 0; } -static int qcow_set_key(struct td_state *bs, const char *key) -{ - struct tdqcow_state *s = (struct tdqcow_state *)bs->private; +static int qcow_set_key(struct tdqcow_state *s, const char *key) +{ uint8_t keybuf[16]; int len, i; @@ -306,10 +322,9 @@ static int qcow_set_key(struct td_state return 0; } -static int async_read(struct tdqcow_state *s, int fd, int size, - uint64_t offset, - char *buf, td_callback_t cb, - int id, uint64_t sector, int qcow_idx, void *private) +static int async_read(struct tdqcow_state *s, int size, + uint64_t offset, char *buf, td_callback_t cb, + int id, uint64_t sector, void *private) { struct iocb *io; struct pending_aio *pio; @@ -325,9 +340,8 @@ static int async_read(struct tdqcow_stat pio->nb_sectors = size/512; pio->buf = buf; pio->sector = sector; - pio->qcow_idx = qcow_idx; - - io_prep_pread(io, fd, buf, size, offset); + + io_prep_pread(io, s->fd, buf, size, offset); io->data = (void *)ioidx; s->iocb_queue[s->iocb_queued++] = io; @@ -335,10 +349,9 @@ static int async_read(struct tdqcow_stat return 1; } -static int async_write(struct tdqcow_state *s, int fd, int size, - uint64_t offset, - char *buf, td_callback_t cb, - int id, uint64_t sector, int qcow_idx, void *private) +static int async_write(struct tdqcow_state *s, int size, + uint64_t offset, char *buf, td_callback_t cb, + int id, uint64_t sector, void *private) { struct iocb *io; struct pending_aio *pio; @@ -354,9 +367,8 @@ static int async_write(struct tdqcow_sta pio->nb_sectors = size/512; pio->buf = buf; pio->sector = sector; - pio->qcow_idx = qcow_idx; - - io_prep_pwrite(io, fd, buf, size, offset); + + io_prep_pwrite(io, s->fd, buf, size, offset); io->data = (void *)ioidx; s->iocb_queue[s->iocb_queued++] = io; @@ -381,17 +393,6 @@ static void aio_unlock(struct tdqcow_sta --s->sector_lock[sector]; return; -} - -/*TODO - Use a freelist*/ -static int get_free_idx(struct tdqcow_state *s) -{ - int i; - - for(i = 0; i < MAX_QCOW_IDS; i++) { - if(s->nr_reqs[i] == 0) return i; - } - return -1; } /* @@ -425,23 +426,23 @@ static int qtruncate(int fd, off_t lengt { int ret, i; int current = 0, rem = 0; - int sectors = (length + DEFAULT_SECTOR_SIZE - 1)/DEFAULT_SECTOR_SIZE; + uint64_t sectors; struct stat st; - char buf[DEFAULT_SECTOR_SIZE]; + char *buf; /* If length is greater than the current file len * we synchronously write zeroes to the end of the * file, otherwise we truncate the length down */ - memset(buf, 0x00, DEFAULT_SECTOR_SIZE); ret = fstat(fd, &st); - if (ret == -1) + if (ret == -1) return -1; if (S_ISBLK(st.st_mode)) return 0; - + + sectors = (length + DEFAULT_SECTOR_SIZE - 1)/DEFAULT_SECTOR_SIZE; current = (st.st_size + DEFAULT_SECTOR_SIZE - 1)/DEFAULT_SECTOR_SIZE; - rem = st.st_size % DEFAULT_SECTOR_SIZE; + rem = st.st_size % DEFAULT_SECTOR_SIZE; /* If we are extending this file, we write zeros to the end -- * this tries to ensure that the extents allocated wind up being @@ -449,28 +450,40 @@ static int qtruncate(int fd, off_t lengt */ if(st.st_size < sectors * DEFAULT_SECTOR_SIZE) { /*We are extending the file*/ + if ((ret = posix_memalign((void **)&buf, + 512, DEFAULT_SECTOR_SIZE))) { + DPRINTF("posix_memalign failed: %d\n", ret); + return -1; + } + memset(buf, 0x00, DEFAULT_SECTOR_SIZE); if (lseek(fd, 0, SEEK_END)==-1) { - fprintf(stderr, - "Lseek EOF failed (%d), internal error\n", + DPRINTF("Lseek EOF failed (%d), internal error\n", errno); + free(buf); return -1; } if (rem) { ret = write(fd, buf, rem); - if (ret != rem) + if (ret != rem) { + DPRINTF("write failed: ret = %d, err = %s\n", + ret, strerror(errno)); + free(buf); return -1; + } } for (i = current; i < sectors; i++ ) { ret = write(fd, buf, DEFAULT_SECTOR_SIZE); - if (ret != DEFAULT_SECTOR_SIZE) + if (ret != DEFAULT_SECTOR_SIZE) { + DPRINTF("write failed: ret = %d, err = %s\n", + ret, strerror(errno)); + free(buf); return -1; - } - + } + } + free(buf); } else if(sparse && (st.st_size > sectors * DEFAULT_SECTOR_SIZE)) - if (ftruncate(fd, sectors * DEFAULT_SECTOR_SIZE)==-1) { - fprintf(stderr, - "Ftruncate failed (%d), internal error\n", - errno); + if (ftruncate(fd, (off_t)sectors * DEFAULT_SECTOR_SIZE)==-1) { + DPRINTF("Ftruncate failed (%s)\n", strerror(errno)); return -1; } return 0; @@ -490,12 +503,11 @@ static int qtruncate(int fd, off_t lengt * * return 0 if not allocated. */ -static uint64_t get_cluster_offset(struct td_state *bs, +static uint64_t get_cluster_offset(struct tdqcow_state *s, uint64_t offset, int allocate, int compressed_size, int n_start, int n_end) { - struct tdqcow_state *s = (struct tdqcow_state *)bs->private; int min_index, i, j, l1_index, l2_index, l2_sector, l1_sector; char *tmp_ptr, *tmp_ptr2, *l2_ptr, *l1_ptr; uint64_t l2_offset, *l2_table, cluster_offset, tmp; @@ -550,8 +562,10 @@ static uint64_t get_cluster_offset(struc * entry is written before blocks. */ lseek(s->fd, s->l1_table_offset + (l1_sector << 12), SEEK_SET); - if (write(s->fd, tmp_ptr, 4096) != 4096) + if (write(s->fd, tmp_ptr, 4096) != 4096) { + free(tmp_ptr); return 0; + } free(tmp_ptr); new_l2_table = 1; @@ -716,9 +730,10 @@ found: return cluster_offset; } -static void init_cluster_cache(struct td_state *bs) -{ - struct tdqcow_state *s = (struct tdqcow_state *)bs->private; +static void init_cluster_cache(struct disk_driver *dd) +{ + struct td_state *bs = dd->td_state; + struct tdqcow_state *s = (struct tdqcow_state *)dd->private; uint32_t count = 0; int i, cluster_entries; @@ -727,22 +742,20 @@ static void init_cluster_cache(struct td cluster_entries, s->cluster_size); for (i = 0; i < bs->size; i += cluster_entries) { - if (get_cluster_offset(bs, i << 9, 0, 0, 0, 1)) count++; + if (get_cluster_offset(s, i << 9, 0, 0, 0, 1)) count++; if (count >= L2_CACHE_SIZE) return; } DPRINTF("Finished cluster initialisation, added %d entries\n", count); return; } -static int qcow_is_allocated(struct td_state *bs, int64_t sector_num, +static int qcow_is_allocated(struct tdqcow_state *s, int64_t sector_num, int nb_sectors, int *pnum) { - struct tdqcow_state *s = (struct tdqcow_state *)bs->private; - int index_in_cluster, n; uint64_t cluster_offset; - cluster_offset = get_cluster_offset(bs, sector_num << 9, 0, 0, 0, 0); + cluster_offset = get_cluster_offset(s, sector_num << 9, 0, 0, 0, 0); index_in_cluster = sector_num & (s->cluster_sectors - 1); n = s->cluster_sectors - index_in_cluster; if (n > nb_sectors) @@ -800,11 +813,23 @@ static int decompress_cluster(struct tdq return 0; } +static inline void init_fds(struct disk_driver *dd) +{ + int i; + struct tdqcow_state *s = (struct tdqcow_state *)dd->private; + + for(i = 0; i < MAX_IOFD; i++) + dd->io_fd[i] = 0; + + dd->io_fd[0] = s->poll_fd; +} + /* Open the disk file and initialize qcow state. */ -int tdqcow_open (struct td_state *bs, const char *name) +int tdqcow_open (struct disk_driver *dd, const char *name) { int fd, len, i, shift, ret, size, l1_table_size; - struct tdqcow_state *s = (struct tdqcow_state *)bs->private; + struct td_state *bs = dd->td_state; + struct tdqcow_state *s = (struct tdqcow_state *)dd->private; char *buf; QCowHeader *header; QCowHeader_ext *exthdr; @@ -812,10 +837,6 @@ int tdqcow_open (struct td_state *bs, co uint64_t final_cluster = 0; DPRINTF("QCOW: Opening %s\n",name); - /* set up a pipe so that we can hand back a poll fd that won't fire.*/ - ret = pipe(s->poll_pipe); - if (ret != 0) - return (0 - errno); fd = open(name, O_RDWR | O_DIRECT | O_LARGEFILE); if (fd < 0) { @@ -826,7 +847,7 @@ int tdqcow_open (struct td_state *bs, co s->fd = fd; asprintf(&s->name,"%s", name); - ASSERT(sizeof(header) < 512); + ASSERT(sizeof(QCowHeader) + sizeof(QCowHeader_ext) < 512); ret = posix_memalign((void **)&buf, 512, 512); if (ret != 0) goto fail; @@ -861,7 +882,9 @@ int tdqcow_open (struct td_state *bs, co s->cluster_alloc = s->l2_size; bs->size = header->size / 512; s->cluster_offset_mask = (1LL << (63 - s->cluster_bits)) - 1; - + s->backing_file_offset = header->backing_file_offset; + s->backing_file_size = header->backing_file_size; + /* read the level 1 table */ shift = s->cluster_bits + s->l2_bits; s->l1_size = (header->size + (1LL << shift) - 1) >> shift; @@ -887,7 +910,7 @@ int tdqcow_open (struct td_state *bs, co if (read(fd, s->l1_table, l1_table_size) != l1_table_size) goto fail; - for(i = 0;i < s->l1_size; i++) { + for(i = 0; i < s->l1_size; i++) { //be64_to_cpus(&s->l1_table[i]); //DPRINTF("L1[%d] => %llu\n", i, s->l1_table[i]); if (s->l1_table[i] > final_cluster) @@ -907,41 +930,15 @@ int tdqcow_open (struct td_state *bs, co if(ret != 0) goto fail; s->cluster_cache_offset = -1; - /* read the backing file name */ - s->bfd = -1; - if (header->backing_file_offset != 0) { - DPRINTF("Reading backing file data\n"); - len = header->backing_file_size; - if (len > 1023) - len = 1023; - - /*TODO - Fix read size for O_DIRECT and use original fd!*/ - fd = open(name, O_RDONLY | O_LARGEFILE); - - lseek(fd, header->backing_file_offset, SEEK_SET); - if (read(fd, bs->backing_file, len) != len) - goto fail; - bs->backing_file[len] = '\0'; - close(fd); - /***********************************/ - - /*Open backing file*/ - fd = open(bs->backing_file, O_RDONLY | O_DIRECT | O_LARGEFILE); - if (fd < 0) { - DPRINTF("Unable to open backing file: %s\n", - bs->backing_file); - goto fail; - } - s->bfd = fd; + if (s->backing_file_offset != 0) s->cluster_alloc = 1; /*Cannot use pre-alloc*/ - } bs->sector_size = 512; bs->info = 0; /*Detect min_cluster_alloc*/ s->min_cluster_alloc = 1; /*Default*/ - if (s->bfd == -1 && (s->l1_table_offset % 4096 == 0) ) { + if (s->backing_file_offset == 0 && s->l1_table_offset % 4096 == 0) { /*We test to see if the xen magic # exists*/ exthdr = (QCowHeader_ext *)(buf + sizeof(QCowHeader)); be32_to_cpus(&exthdr->xmagic); @@ -962,10 +959,11 @@ int tdqcow_open (struct td_state *bs, co } end_xenhdr: - if (init_aio_state(bs)!=0) { + if (init_aio_state(dd)!=0) { DPRINTF("Unable to initialise AIO state\n"); goto fail; } + init_fds(dd); s->fd_end = (final_cluster == 0 ? (s->l1_table_offset + l1_table_size) : (final_cluster + s->cluster_size)); @@ -981,213 +979,145 @@ fail: return -1; } - int tdqcow_queue_read(struct td_state *bs, uint64_t sector, - int nb_sectors, char *buf, td_callback_t cb, - int id, void *private) -{ - struct tdqcow_state *s = (struct tdqcow_state *)bs->private; - int ret = 0, index_in_cluster, n, i, qcow_idx, asubmit = 0; - uint64_t cluster_offset; +int tdqcow_queue_read(struct disk_driver *dd, uint64_t sector, + int nb_sectors, char *buf, td_callback_t cb, + int id, void *private) +{ + struct tdqcow_state *s = (struct tdqcow_state *)dd->private; + int ret = 0, index_in_cluster, n, i, rsp = 0; + uint64_t cluster_offset, sec, nr_secs; + + sec = sector; + nr_secs = nb_sectors; /*Check we can get a lock*/ - for (i = 0; i < nb_sectors; i++) - if (!aio_can_lock(s, sector + i)) { - DPRINTF("AIO_CAN_LOCK failed [%llu]\n", - (long long) sector + i); - return -EBUSY; - } - + for (i = 0; i < nb_sectors; i++) + if (!aio_can_lock(s, sector + i)) + return cb(dd, -EBUSY, sector, nb_sectors, id, private); + /*We store a local record of the request*/ - qcow_idx = get_free_idx(s); while (nb_sectors > 0) { cluster_offset = - get_cluster_offset(bs, sector << 9, 0, 0, 0, 0); + get_cluster_offset(s, sector << 9, 0, 0, 0, 0); index_in_cluster = sector & (s->cluster_sectors - 1); n = s->cluster_sectors - index_in_cluster; if (n > nb_sectors) n = nb_sectors; - if (s->iocb_free_count == 0 || !aio_lock(s, sector)) { - DPRINTF("AIO_LOCK or iocb_free_count (%d) failed" - "[%llu]\n", s->iocb_free_count, - (long long) sector); - return -ENOMEM; - } + if (s->iocb_free_count == 0 || !aio_lock(s, sector)) + return cb(dd, -EBUSY, sector, nb_sectors, id, private); - if (!cluster_offset && (s->bfd > 0)) { - s->nr_reqs[qcow_idx]++; - asubmit += async_read(s, s->bfd, n * 512, sector << 9, - buf, cb, id, sector, - qcow_idx, private); - } else if(!cluster_offset) { - memset(buf, 0, 512 * n); + if(!cluster_offset) { aio_unlock(s, sector); + ret = cb(dd, BLK_NOT_ALLOCATED, + sector, n, id, private); + if (ret == -EBUSY) { + /* mark remainder of request + * as busy and try again later */ + return cb(dd, -EBUSY, sector + n, + nb_sectors - n, id, private); + } else rsp += ret; } else if (cluster_offset & QCOW_OFLAG_COMPRESSED) { + aio_unlock(s, sector); if (decompress_cluster(s, cluster_offset) < 0) { - ret = -1; + rsp += cb(dd, -EIO, sector, + nb_sectors, id, private); goto done; } memcpy(buf, s->cluster_cache + index_in_cluster * 512, 512 * n); - } else { - s->nr_reqs[qcow_idx]++; - asubmit += async_read(s, s->fd, n * 512, - (cluster_offset + - index_in_cluster * 512), - buf, cb, id, sector, - qcow_idx, private); + rsp += cb(dd, 0, sector, n, id, private); + } else { + async_read(s, n * 512, + (cluster_offset + index_in_cluster * 512), + buf, cb, id, sector, private); } nb_sectors -= n; sector += n; buf += n * 512; } done: - /*Callback if no async requests outstanding*/ - if (!asubmit) return cb(bs, ret == -1 ? -1 : 0, id, private); - - return 0; -} - - int tdqcow_queue_write(struct td_state *bs, uint64_t sector, - int nb_sectors, char *buf, td_callback_t cb, - int id, void *private) -{ - struct tdqcow_state *s = (struct tdqcow_state *)bs->private; - int ret = 0, index_in_cluster, n, i, qcow_idx, asubmit = 0; - uint64_t cluster_offset; + return rsp; +} + +int tdqcow_queue_write(struct disk_driver *dd, uint64_t sector, + int nb_sectors, char *buf, td_callback_t cb, + int id, void *private) +{ + struct tdqcow_state *s = (struct tdqcow_state *)dd->private; + int ret = 0, index_in_cluster, n, i; + uint64_t cluster_offset, sec, nr_secs; + + sec = sector; + nr_secs = nb_sectors; /*Check we can get a lock*/ for (i = 0; i < nb_sectors; i++) - if (!aio_can_lock(s, sector + i)) { - DPRINTF("AIO_CAN_LOCK failed [%llu]\n", - (long long) (sector + i)); - return -EBUSY; - } + if (!aio_can_lock(s, sector + i)) + return cb(dd, -EBUSY, sector, nb_sectors, id, private); /*We store a local record of the request*/ - qcow_idx = get_free_idx(s); while (nb_sectors > 0) { index_in_cluster = sector & (s->cluster_sectors - 1); n = s->cluster_sectors - index_in_cluster; if (n > nb_sectors) n = nb_sectors; - if (s->iocb_free_count == 0 || !aio_lock(s, sector)){ - DPRINTF("AIO_LOCK or iocb_free_count (%d) failed" - "[%llu]\n", s->iocb_free_count, - (long long) sector); - return -ENOMEM; - } - - if (!IS_ZERO(buf,n * 512)) { - - cluster_offset = get_cluster_offset(bs, sector << 9, - 1, 0, - index_in_cluster, - index_in_cluster+n - ); - if (!cluster_offset) { - DPRINTF("Ooops, no write cluster offset!\n"); - ret = -1; - goto done; - } - - if (s->crypt_method) { - encrypt_sectors(s, sector, s->cluster_data, - (unsigned char *)buf, n, 1, - &s->aes_encrypt_key); - s->nr_reqs[qcow_idx]++; - asubmit += async_write(s, s->fd, n * 512, - (cluster_offset + - index_in_cluster*512), - (char *)s->cluster_data, - cb, id, sector, - qcow_idx, private); - } else { - s->nr_reqs[qcow_idx]++; - asubmit += async_write(s, s->fd, n * 512, - (cluster_offset + - index_in_cluster*512), - buf, cb, id, sector, - qcow_idx, private); - } + if (s->iocb_free_count == 0 || !aio_lock(s, sector)) + return cb(dd, -EBUSY, sector, nb_sectors, id, private); + + cluster_offset = get_cluster_offset(s, sector << 9, 1, 0, + index_in_cluster, + index_in_cluster+n); + if (!cluster_offset) { + DPRINTF("Ooops, no write cluster offset!\n"); + return cb(dd, -EIO, sector, nb_sectors, id, private); + } + + if (s->crypt_method) { + encrypt_sectors(s, sector, s->cluster_data, + (unsigned char *)buf, n, 1, + &s->aes_encrypt_key); + async_write(s, n * 512, + (cluster_offset + index_in_cluster*512), + (char *)s->cluster_data, cb, id, sector, + private); } else { - /*Write data contains zeros, but we must check to see - if cluster already allocated*/ - cluster_offset = get_cluster_offset(bs, sector << 9, - 0, 0, - index_in_cluster, - index_in_cluster+n - ); - if(cluster_offset) { - if (s->crypt_method) { - encrypt_sectors(s, sector, - s->cluster_data, - (unsigned char *)buf, - n, 1, - &s->aes_encrypt_key); - s->nr_reqs[qcow_idx]++; - asubmit += async_write(s, s->fd, - n * 512, - (cluster_offset+ - index_in_cluster * 512), - (char *)s->cluster_data, cb, id, sector, - qcow_idx, private); - } else { - s->nr_reqs[qcow_idx]++; - asubmit += async_write(s, s->fd, n*512, - cluster_offset + index_in_cluster * 512, - buf, cb, id, sector, - qcow_idx, private); - } - } - else aio_unlock(s, sector); - } + async_write(s, n * 512, + (cluster_offset + index_in_cluster*512), + buf, cb, id, sector, private); + } + nb_sectors -= n; sector += n; buf += n * 512; } s->cluster_cache_offset = -1; /* disable compressed cache */ -done: - /*Callback if no async requests outstanding*/ - if (!asubmit) return cb(bs, ret == -1 ? -1 : 0, id, private); - return 0; } -int tdqcow_submit(struct td_state *bs) +int tdqcow_submit(struct disk_driver *dd) { int ret; - struct tdqcow_state *prv = (struct tdqcow_state *)bs->private; - - ret = io_submit(prv->aio_ctx, prv->iocb_queued, prv->iocb_queue); + struct tdqcow_state *prv = (struct tdqcow_state *)dd->private; + + if (!prv->iocb_queued) + return 0; + + ret = io_submit(prv->aio_ctx, prv->iocb_queued, prv->iocb_queue); /* XXX: TODO: Handle error conditions here. */ /* Success case: */ prv->iocb_queued = 0; - return ret; -} - - -int *tdqcow_get_fd(struct td_state *bs) -{ - struct tdqcow_state *s = (struct tdqcow_state *)bs->private; - int *fds, i; - - fds = malloc(sizeof(int) * MAX_IOFD); - /*initialise the FD array*/ - for(i=0;i<MAX_IOFD;i++) fds[i] = 0; - - fds[0] = s->poll_fd; - return fds; -} - -int tdqcow_close(struct td_state *bs) -{ - struct tdqcow_state *s = (struct tdqcow_state *)bs->private; + return 0; +} + +int tdqcow_close(struct disk_driver *dd) +{ + struct tdqcow_state *s = (struct tdqcow_state *)dd->private; uint32_t cksum, out; int fd, offset; @@ -1203,6 +1133,7 @@ int tdqcow_close(struct td_state *bs) close(fd); } + io_destroy(s->aio_ctx); free(s->name); free(s->l1_table); free(s->l2_cache); @@ -1212,11 +1143,11 @@ int tdqcow_close(struct td_state *bs) return 0; } -int tdqcow_do_callbacks(struct td_state *s, int sid) +int tdqcow_do_callbacks(struct disk_driver *dd, int sid) { int ret, i, rsp = 0,*ptr; struct io_event *ep; - struct tdqcow_state *prv = (struct tdqcow_state *)s->private; + struct tdqcow_state *prv = (struct tdqcow_state *)dd->private; if (sid > MAX_IOFD) return 1; @@ -1224,25 +1155,24 @@ int tdqcow_do_callbacks(struct td_state ret = io_getevents(prv->aio_ctx, 0, MAX_AIO_REQS, prv->aio_events, NULL); - for (ep=prv->aio_events, i = ret; i-->0; ep++) { + for (ep = prv->aio_events, i = ret; i-- > 0; ep++) { struct iocb *io = ep->obj; struct pending_aio *pio; pio = &prv->pending_aio[(long)io->data]; aio_unlock(prv, pio->sector); - if (pio->id >= 0) { - if (prv->crypt_method) - encrypt_sectors(prv, pio->sector, - (unsigned char *)pio->buf, - (unsigned char *)pio->buf, - pio->nb_sectors, 0, - &prv->aes_decrypt_key); - prv->nr_reqs[pio->qcow_idx]--; - if (prv->nr_reqs[pio->qcow_idx] == 0) - rsp += pio->cb(s, ep->res == io->u.c.nbytes ? 0 : 1, pio->id, - pio->private); - } else if (pio->id == -2) free(pio->buf); + + if (prv->crypt_method) + encrypt_sectors(prv, pio->sector, + (unsigned char *)pio->buf, + (unsigned char *)pio->buf, + pio->nb_sectors, 0, + &prv->aes_decrypt_key); + + rsp += pio->cb(dd, ep->res == io->u.c.nbytes ? 0 : 1, + pio->sector, pio->nb_sectors, + pio->id, pio->private); prv->iocb_free[prv->iocb_free_count++] = io; } @@ -1250,7 +1180,7 @@ int tdqcow_do_callbacks(struct td_state } int qcow_create(const char *filename, uint64_t total_size, - const char *backing_file, int sparse) + const char *backing_file, int sparse) { int fd, header_size, backing_filename_len, l1_size, i; int shift, length, adjust, flags = 0, ret = 0; @@ -1391,9 +1321,8 @@ int qcow_create(const char *filename, ui return 0; } -int qcow_make_empty(struct td_state *bs) -{ - struct tdqcow_state *s = (struct tdqcow_state *)bs->private; +int qcow_make_empty(struct tdqcow_state *s) +{ uint32_t l1_length = s->l1_size * sizeof(uint64_t); memset(s->l1_table, 0, l1_length); @@ -1412,19 +1341,16 @@ int qcow_make_empty(struct td_state *bs) return 0; } -int qcow_get_cluster_size(struct td_state *bs) -{ - struct tdqcow_state *s = (struct tdqcow_state *)bs->private; - +int qcow_get_cluster_size(struct tdqcow_state *s) +{ return s->cluster_size; } /* XXX: put compressed sectors first, then all the cluster aligned tables to avoid losing bytes in alignment */ -int qcow_compress_cluster(struct td_state *bs, int64_t sector_num, +int qcow_compress_cluster(struct tdqcow_state *s, int64_t sector_num, const uint8_t *buf) { - struct tdqcow_state *s = (struct tdqcow_state *)bs->private; z_stream strm; int ret, out_len; uint8_t *out_buf; @@ -1463,7 +1389,7 @@ int qcow_compress_cluster(struct td_stat /* could not compress: write normal cluster */ //tdqcow_queue_write(bs, sector_num, buf, s->cluster_sectors); } else { - cluster_offset = get_cluster_offset(bs, sector_num << 9, 2, + cluster_offset = get_cluster_offset(s, sector_num << 9, 2, out_len, 0, 0); cluster_offset &= s->cluster_offset_mask; lseek(s->fd, cluster_offset, SEEK_SET); @@ -1477,15 +1403,54 @@ int qcow_compress_cluster(struct td_stat return 0; } +int tdqcow_has_parent(struct disk_driver *dd) +{ + struct tdqcow_state *s = (struct tdqcow_state *)dd->private; + return (s->backing_file_offset ? 1 : 0); +} + +int tdqcow_get_parent(struct disk_driver *cdd, struct disk_driver *pdd) +{ + off_t off; + char *buf, *filename; + int len, secs, ret = -1; + struct tdqcow_state *child = (struct tdqcow_state *)cdd->private; + + if (!child->backing_file_offset) + return -1; + + /* read the backing file name */ + len = child->backing_file_size; + off = child->backing_file_offset - (child->backing_file_offset % 512); + secs = (len + (child->backing_file_offset - off) + 511) >> 9; + + if (posix_memalign((void **)&buf, 512, secs << 9)) + return -1; + + if (lseek(child->fd, off, SEEK_SET) == (off_t)-1) + goto out; + + if (read(child->fd, buf, secs << 9) != secs << 9) + goto out; + filename = buf + (child->backing_file_offset - off); + filename[len] = '\0'; + + /*Open backing file*/ + ret = tdqcow_open(pdd, filename); + out: + free(buf); + return ret; +} + struct tap_disk tapdisk_qcow = { - "tapdisk_qcow", - sizeof(struct tdqcow_state), - tdqcow_open, - tdqcow_queue_read, - tdqcow_queue_write, - tdqcow_submit, - tdqcow_get_fd, - tdqcow_close, - tdqcow_do_callbacks, + .disk_type = "tapdisk_qcow", + .private_data_size = sizeof(struct tdqcow_state), + .td_open = tdqcow_open, + .td_queue_read = tdqcow_queue_read, + .td_queue_write = tdqcow_queue_write, + .td_submit = tdqcow_submit, + .td_has_parent = tdqcow_has_parent, + .td_get_parent = tdqcow_get_parent, + .td_close = tdqcow_close, + .td_do_callbacks = tdqcow_do_callbacks, }; - diff -r 04c23c1ef888 -r d907467f08cd tools/blktap/drivers/block-ram.c --- a/tools/blktap/drivers/block-ram.c Sun Feb 18 16:13:13 2007 -0700 +++ b/tools/blktap/drivers/block-ram.c Tue Feb 20 12:58:22 2007 -0700 @@ -123,14 +123,25 @@ static int get_image_info(struct td_stat return 0; } +static inline void init_fds(struct disk_driver *dd) +{ + int i; + struct tdram_state *prv = (struct tdram_state *)dd->private; + + for(i =0 ; i < MAX_IOFD; i++) + dd->io_fd[i] = 0; + + dd->io_fd[0] = prv->poll_pipe[0]; +} + /* Open the disk file and initialize ram state. */ -int tdram_open (struct td_state *s, const char *name) -{ +int tdram_open (struct disk_driver *dd, const char *name) +{ + char *p; + uint64_t size; int i, fd, ret = 0, count = 0; - struct tdram_state *prv = (struct tdram_state *)s->private; - uint64_t size; - char *p; - s->private = prv; + struct td_state *s = dd->td_state; + struct tdram_state *prv = (struct tdram_state *)dd->private; connections++; @@ -209,88 +220,80 @@ int tdram_open (struct td_state *s, cons ret = 0; } + init_fds(dd); done: return ret; } - int tdram_queue_read(struct td_state *s, uint64_t sector, - int nb_sectors, char *buf, td_callback_t cb, - int id, void *private) -{ - struct tdram_state *prv = (struct tdram_state *)s->private; + int tdram_queue_read(struct disk_driver *dd, uint64_t sector, + int nb_sectors, char *buf, td_callback_t cb, + int id, void *private) +{ + struct td_state *s = dd->td_state; + struct tdram_state *prv = (struct tdram_state *)dd->private; int size = nb_sectors * s->sector_size; uint64_t offset = sector * (uint64_t)s->sector_size; - int ret; memcpy(buf, img + offset, size); - ret = size; - - cb(s, (ret < 0) ? ret: 0, id, private); - - return ret; -} - - int tdram_queue_write(struct td_state *s, uint64_t sector, - int nb_sectors, char *buf, td_callback_t cb, - int id, void *private) -{ - struct tdram_state *prv = (struct tdram_state *)s->private; + + return cb(dd, 0, sector, nb_sectors, id, private); +} + +int tdram_queue_write(struct disk_driver *dd, uint64_t sector, + int nb_sectors, char *buf, td_callback_t cb, + int id, void *private) +{ + struct td_state *s = dd->td_state; + struct tdram_state *prv = (struct tdram_state *)dd->private; int size = nb_sectors * s->sector_size; uint64_t offset = sector * (uint64_t)s->sector_size; - int ret; - - /*We assume that write access is controlled at a higher level for multiple disks*/ + + /* We assume that write access is controlled + * at a higher level for multiple disks */ memcpy(img + offset, buf, size); - ret = size; - - cb(s, (ret < 0) ? ret : 0, id, private); - - return ret; + + return cb(dd, 0, sector, nb_sectors, id, private); } -int tdram_submit(struct td_state *s) +int tdram_submit(struct disk_driver *dd) { return 0; } - -int *tdram_get_fd(struct td_state *s) -{ - struct tdram_state *prv = (struct tdram_state *)s->private; - int *fds, i; - - fds = malloc(sizeof(int) * MAX_IOFD); - /*initialise the FD array*/ - for(i=0;i<MAX_IOFD;i++) fds[i] = 0; - - fds[0] = prv->poll_pipe[0]; - return fds; -} - -int tdram_close(struct td_state *s) -{ - struct tdram_state *prv = (struct tdram_state *)s->private; +int tdram_close(struct disk_driver *dd) +{ + struct tdram_state *prv = (struct tdram_state *)dd->private; connections--; return 0; } -int tdram_do_callbacks(struct td_state *s, int sid) +int tdram_do_callbacks(struct disk_driver *dd, int sid) { /* always ask for a kick */ return 1; } +int tdram_has_parent(struct disk_driver *dd) +{ + return 0; +} + +int tdram_get_parent(struct disk_driver *dd, struct disk_driver *parent) +{ + return -EINVAL; +} + struct tap_disk tapdisk_ram = { - "tapdisk_ram", - sizeof(struct tdram_state), - tdram_open, - tdram_queue_read, - tdram_queue_write, - tdram_submit, - tdram_get_fd, - tdram_close, - tdram_do_callbacks, + .disk_type = "tapdisk_ram", + .private_data_size = sizeof(struct tdram_state), + .td_open = tdram_open, + .td_queue_read = tdram_queue_read, + .td_queue_write = tdram_queue_write, + .td_submit = tdram_submit, + .td_has_parent = tdram_has_parent, + .td_get_parent = tdram_get_parent, + .td_close = tdram_close, + .td_do_callbacks = tdram_do_callbacks, }; - diff -r 04c23c1ef888 -r d907467f08cd tools/blktap/drivers/block-sync.c --- a/tools/blktap/drivers/block-sync.c Sun Feb 18 16:13:13 2007 -0700 +++ b/tools/blktap/drivers/block-sync.c Tue Feb 20 12:58:22 2007 -0700 @@ -106,12 +106,23 @@ static int get_image_info(struct td_stat return 0; } +static inline void init_fds(struct disk_driver *dd) +{ + int i; + struct tdsync_state *prv = (struct tdsync_state *)dd->private; + + for(i = 0; i < MAX_IOFD; i++) + dd->io_fd[i] = 0; + + dd->io_fd[0] = prv->poll_pipe[0]; +} + /* Open the disk file and initialize aio state. */ -int tdsync_open (struct td_state *s, const char *name) +int tdsync_open (struct disk_driver *dd, const char *name) { int i, fd, ret = 0; - struct tdsync_state *prv = (struct tdsync_state *)s->private; - s->private = prv; + struct td_state *s = dd->td_state; + struct tdsync_state *prv = (struct tdsync_state *)dd->private; /* set up a pipe so that we can hand back a poll fd that won't fire.*/ ret = pipe(prv->poll_pipe); @@ -138,16 +149,18 @@ int tdsync_open (struct td_state *s, con prv->fd = fd; + init_fds(dd); ret = get_image_info(s, fd); done: return ret; } - int tdsync_queue_read(struct td_state *s, uint64_t sector, + int tdsync_queue_read(struct disk_driver *dd, uint64_t sector, int nb_sectors, char *buf, td_callback_t cb, int id, void *private) { - struct tdsync_state *prv = (struct tdsync_state *)s->private; + struct td_state *s = dd->td_state; + struct tdsync_state *prv = (struct tdsync_state *)dd->private; int size = nb_sectors * s->sector_size; uint64_t offset = sector * (uint64_t)s->sector_size; int ret; @@ -162,16 +175,15 @@ done: } } else ret = 0 - errno; - cb(s, (ret < 0) ? ret: 0, id, private); - - return 1; -} - - int tdsync_queue_write(struct td_state *s, uint64_t sector, + return cb(dd, (ret < 0) ? ret: 0, sector, nb_sectors, id, private); +} + + int tdsync_queue_write(struct disk_driver *dd, uint64_t sector, int nb_sectors, char *buf, td_callback_t cb, int id, void *private) { - struct tdsync_state *prv = (struct tdsync_state *)s->private; + struct td_state *s = dd->td_state; + struct tdsync_state *prv = (struct tdsync_state *)dd->private; int size = nb_sectors * s->sector_size; uint64_t offset = sector * (uint64_t)s->sector_size; int ret = 0; @@ -186,34 +198,17 @@ done: } } else ret = 0 - errno; - cb(s, (ret < 0) ? ret : 0, id, private); - - return 1; + return cb(dd, (ret < 0) ? ret : 0, sector, nb_sectors, id, private); } -int tdsync_submit(struct td_state *s) +int tdsync_submit(struct disk_driver *dd) { return 0; } - -int *tdsync_get_fd(struct td_state *s) -{ - struct tdsync_state *prv = (struct tdsync_state *)s->private; - - int *fds, i; - - fds = malloc(sizeof(int) * MAX_IOFD); - /*initialise the FD array*/ - for(i=0;i<MAX_IOFD;i++) fds[i] = 0; - - fds[0] = prv->poll_pipe[0]; - return fds; -} - -int tdsync_close(struct td_state *s) -{ - struct tdsync_state *prv = (struct tdsync_state *)s->private; +int tdsync_close(struct disk_driver *dd) +{ + struct tdsync_state *prv = (struct tdsync_state *)dd->private; close(prv->fd); close(prv->poll_pipe[0]); @@ -222,21 +217,31 @@ int tdsync_close(struct td_state *s) return 0; } -int tdsync_do_callbacks(struct td_state *s, int sid) +int tdsync_do_callbacks(struct disk_driver *dd, int sid) { /* always ask for a kick */ return 1; } +int tdsync_has_parent(struct disk_driver *dd) +{ + return 0; +} + +int tdsync_get_parent(struct disk_driver *dd, struct disk_driver *parent) +{ + return -EINVAL; +} + struct tap_disk tapdisk_sync = { - "tapdisk_sync", - sizeof(struct tdsync_state), - tdsync_open, - tdsync_queue_read, - tdsync_queue_write, - tdsync_submit, - tdsync_get_fd, - tdsync_close, - tdsync_do_callbacks, + .disk_type = "tapdisk_sync", + .private_data_size = sizeof(struct tdsync_state), + .td_open = tdsync_open, + .td_queue_read = tdsync_queue_read, + .td_queue_write = tdsync_queue_write, + .td_submit = tdsync_submit, + .td_has_parent = tdsync_has_parent, + .td_get_parent = tdsync_get_parent, + .td_close = tdsync_close, + .td_do_callbacks = tdsync_do_callbacks, }; - diff -r 04c23c1ef888 -r d907467f08cd tools/blktap/drivers/block-vmdk.c --- a/tools/blktap/drivers/block-vmdk.c Sun Feb 18 16:13:13 2007 -0700 +++ b/tools/blktap/drivers/block-vmdk.c Tue Feb 20 12:58:22 2007 -0700 @@ -107,14 +107,25 @@ struct tdvmdk_state { unsigned int cluster_sectors; }; +static inline void init_fds(struct disk_driver *dd) +{ + int i; + struct tdvmdk_state *prv = (struct tdvmdk_state *)dd->private; + + for (i = 0; i < MAX_IOFD; i++) + dd->io_fd[i] = 0; + + dd->io_fd[0] = prv->poll_pipe[0]; +} /* Open the disk file and initialize aio state. */ -static int tdvmdk_open (struct td_state *s, const char *name) +static int tdvmdk_open (struct disk_driver *dd, const char *name) { int ret, fd; int l1_size, i; uint32_t magic; - struct tdvmdk_state *prv = (struct tdvmdk_state *)s->private; + struct td_state *s = dd->td_state; + struct tdvmdk_state *prv = (struct tdvmdk_state *)dd->private; /* set up a pipe so that we can hand back a poll fd that won't fire.*/ ret = pipe(prv->poll_pipe); @@ -206,6 +217,7 @@ static int tdvmdk_open (struct td_state if (!prv->l2_cache) goto fail; prv->fd = fd; + init_fds(dd); DPRINTF("VMDK File opened successfully\n"); return 0; @@ -218,10 +230,9 @@ fail: return -1; } -static uint64_t get_cluster_offset(struct td_state *s, +static uint64_t get_cluster_offset(struct tdvmdk_state *prv, uint64_t offset, int allocate) { - struct tdvmdk_state *prv = (struct tdvmdk_state *)s->private; unsigned int l1_index, l2_offset, l2_index; int min_index, i, j; uint32_t min_count, *l2_table, tmp; @@ -291,16 +302,17 @@ static uint64_t get_cluster_offset(struc return cluster_offset; } -static int tdvmdk_queue_read(struct td_state *s, uint64_t sector, +static int tdvmdk_queue_read(struct disk_driver *dd, uint64_t sector, int nb_sectors, char *buf, td_callback_t cb, int id, void *private) { - struct tdvmdk_state *prv = (struct tdvmdk_state *)s->private; + struct tdvmdk_state *prv = (struct tdvmdk_state *)dd->private; int index_in_cluster, n; uint64_t cluster_offset; int ret = 0; + while (nb_sectors > 0) { - cluster_offset = get_cluster_offset(s, sector << 9, 0); + cluster_offset = get_cluster_offset(prv, sector << 9, 0); index_in_cluster = sector % prv->cluster_sectors; n = prv->cluster_sectors - index_in_cluster; if (n > nb_sectors) @@ -321,27 +333,24 @@ static int tdvmdk_queue_read(struct td_s buf += n * 512; } done: - cb(s, ret == -1 ? -1 : 0, id, private); - - return 1; -} - -static int tdvmdk_queue_write(struct td_state *s, uint64_t sector, + return cb(dd, ret == -1 ? -1 : 0, sector, nb_sectors, id, private); +} + +static int tdvmdk_queue_write(struct disk_driver *dd, uint64_t sector, int nb_sectors, char *buf, td_callback_t cb, int id, void *private) { - struct tdvmdk_state *prv = (struct tdvmdk_state *)s->private; + struct tdvmdk_state *prv = (struct tdvmdk_state *)dd->private; int index_in_cluster, n; uint64_t cluster_offset; int ret = 0; - while (nb_sectors > 0) { index_in_cluster = sector & (prv->cluster_sectors - 1); n = prv->cluster_sectors - index_in_cluster; if (n > nb_sectors) n = nb_sectors; - cluster_offset = get_cluster_offset(s, sector << 9, 1); + cluster_offset = get_cluster_offset(prv, sector << 9, 1); if (!cluster_offset) { ret = -1; goto done; @@ -358,33 +367,17 @@ static int tdvmdk_queue_write(struct td buf += n * 512; } done: - cb(s, ret == -1 ? -1 : 0, id, private); - - return 1; + return cb(dd, ret == -1 ? -1 : 0, sector, nb_sectors, id, private); } -static int tdvmdk_submit(struct td_state *s) +static int tdvmdk_submit(struct disk_driver *dd) { return 0; } - -static int *tdvmdk_get_fd(struct td_state *s) -{ - struct tdvmdk_state *prv = (struct tdvmdk_state *)s->private; - int *fds, i; - - fds = malloc(sizeof(int) * MAX_IOFD); - /*initialise the FD array*/ - for (i=0;i<MAX_IOFD;i++) fds[i] = 0; - - fds[0] = prv->poll_pipe[0]; - return fds; -} - -static int tdvmdk_close(struct td_state *s) -{ - struct tdvmdk_state *prv = (struct tdvmdk_state *)s->private; +static int tdvmdk_close(struct disk_driver *dd) +{ + struct tdvmdk_state *prv = (struct tdvmdk_state *)dd->private; safer_free(prv->l1_table); safer_free(prv->l1_backup_table); @@ -395,21 +388,31 @@ static int tdvmdk_close(struct td_state return 0; } -static int tdvmdk_do_callbacks(struct td_state *s, int sid) +static int tdvmdk_do_callbacks(struct disk_driver *dd, int sid) { /* always ask for a kick */ return 1; } +static int tdvmdk_has_parent(struct disk_driver *dd) +{ + return 0; +} + +static int tdvmdk_get_parent(struct disk_driver *dd, struct disk_driver *parent) +{ + return -EINVAL; +} + struct tap_disk tapdisk_vmdk = { - "tapdisk_vmdk", - sizeof(struct tdvmdk_state), - tdvmdk_open, - tdvmdk_queue_read, - tdvmdk_queue_write, - tdvmdk_submit, - tdvmdk_get_fd, - tdvmdk_close, - tdvmdk_do_callbacks, + .disk_type = "tapdisk_vmdk", + .private_data_size = sizeof(struct tdvmdk_state), + .td_open = tdvmdk_open, + .td_queue_read = tdvmdk_queue_read, + .td_queue_write = tdvmdk_queue_write, + .td_submit = tdvmdk_submit, + .td_has_parent = tdvmdk_has_parent, + .td_get_parent = tdvmdk_get_parent, + .td_close = tdvmdk_close, + .td_do_callbacks = tdvmdk_do_callbacks, }; - diff -r 04c23c1ef888 -r d907467f08cd tools/blktap/drivers/img2qcow.c --- a/tools/blktap/drivers/img2qcow.c Sun Feb 18 16:13:13 2007 -0700 +++ b/tools/blktap/drivers/img2qcow.c Tue Feb 20 12:58:22 2007 -0700 @@ -147,7 +147,8 @@ static int get_image_info(struct td_stat return 0; } -static int send_responses(struct td_state *s, int res, int idx, void *private) +static int send_responses(struct disk_driver *dd, int res, uint64_t sec, + int nr_secs, int idx, void *private) { if (res < 0) DFPRINTF("AIO FAILURE: res [%d]!\n",res); @@ -159,7 +160,7 @@ static int send_responses(struct td_stat int main(int argc, char *argv[]) { - struct tap_disk *drv; + struct disk_driver dd; struct td_state *s; int ret = -1, fd, len; fd_set readfds; @@ -195,16 +196,17 @@ int main(int argc, char *argv[]) } else DFPRINTF("Qcow file created: size %llu sectors\n", (long long unsigned)s->size); - drv = &tapdisk_qcow; - s->private = malloc(drv->private_data_size); + dd.td_state = s; + dd.drv = &tapdisk_qcow; + dd.private = malloc(dd.drv->private_data_size); /*Open qcow file*/ - if (drv->td_open(s, argv[1])!=0) { + if (dd.drv->td_open(&dd, argv[1])!=0) { DFPRINTF("Unable to open Qcow file [%s]\n",argv[1]); exit(-1); } - io_fd = drv->td_get_fd(s); + io_fd = dd.io_fd; /*Initialise the output string*/ memset(output,0x20,25); @@ -245,9 +247,9 @@ int main(int argc, char *argv[]) len = (len >> 9) << 9; } - ret = drv->td_queue_write(s, i >> 9, - len >> 9, buf, - send_responses, 0, buf); + ret = dd.drv->td_queue_write(&dd, i >> 9, + len >> 9, buf, + send_responses, 0, buf); if (!ret) submit_events++; @@ -261,7 +263,7 @@ int main(int argc, char *argv[]) debug_output(i,s->size << 9); if ((submit_events % 10 == 0) || complete) - drv->td_submit(s); + dd.drv->td_submit(&dd); timeout.tv_usec = 0; } else { @@ -275,14 +277,14 @@ int main(int argc, char *argv[]) ret = select(maxfds + 1, &readfds, (fd_set *) 0, (fd_set *) 0, &timeout); - if (ret > 0) drv->td_do_callbacks(s, 0); + if (ret > 0) dd.drv->td_do_callbacks(&dd, 0); if (complete && (returned_events == submit_events)) running = 0; } memcpy(output+prev+1,"=",1); DFPRINTF("\r%s 100%%\nTRANSFER COMPLETE\n\n", output); - drv->td_close(s); - free(s->private); + dd.drv->td_close(&dd); + free(dd.private); free(s); return 0; diff -r 04c23c1ef888 -r d907467f08cd tools/blktap/drivers/qcow2raw.c --- a/tools/blktap/drivers/qcow2raw.c Sun Feb 18 16:13:13 2007 -0700 +++ b/tools/blktap/drivers/qcow2raw.c Tue Feb 20 12:58:22 2007 -0700 @@ -55,8 +55,7 @@ static int returned_read_events = 0, ret static int returned_read_events = 0, returned_write_events = 0; static int submit_events = 0; static uint32_t read_idx = 0, write_idx = 0; -struct tap_disk *drv1, *drv2; -struct td_state *sqcow, *saio; +struct disk_driver ddqcow, ddaio; static uint64_t prev = 0, written = 0; static char output[25]; @@ -100,7 +99,8 @@ static inline void LOCAL_FD_SET(fd_set * return; } -static int send_write_responses(struct td_state *s, int res, int idx, void *private) +static int send_write_responses(struct disk_driver *dd, int res, uint64_t sec, + int nr_secs, int idx, void *private) { if (res < 0) { DFPRINTF("AIO FAILURE: res [%d]!\n",res); @@ -112,12 +112,13 @@ static int send_write_responses(struct t if (complete && (returned_write_events == submit_events)) write_complete = 1; - debug_output(written, s->size << 9); + debug_output(written, dd->td_state->size << 9); free(private); return 0; } -static int send_read_responses(struct td_state *s, int res, int idx, void *private) +static int send_read_responses(struct disk_driver *dd, int res, uint64_t sec, + int nr_secs, int idx, void *private) { int ret; @@ -128,8 +129,8 @@ static int send_read_responses(struct td if (complete && (returned_read_events == submit_events)) read_complete = 1; - ret = drv2->td_queue_write(saio, idx, BLOCK_PROCESSSZ>>9, private, - send_write_responses, idx, private); + ret = ddaio.drv->td_queue_write(&ddaio, idx, BLOCK_PROCESSSZ>>9, private, + send_write_responses, idx, private); if (ret != 0) { DFPRINTF("ERROR in submitting queue write!\n"); return 0; @@ -137,7 +138,7 @@ static int send_read_responses(struct td if ( (complete && returned_read_events == submit_events) || (returned_read_events % 10 == 0) ) { - drv2->td_submit(saio); + ddaio.drv->td_submit(&ddaio); } return 0; @@ -161,20 +162,20 @@ int main(int argc, char *argv[]) exit(-1); } - sqcow = malloc(sizeof(struct td_state)); - saio = malloc(sizeof(struct td_state)); + ddqcow.td_state = malloc(sizeof(struct td_state)); + ddaio.td_state = malloc(sizeof(struct td_state)); /*Open qcow source file*/ - drv1 = &tapdisk_qcow; - sqcow->private = malloc(drv1->private_data_size); - - if (drv1->td_open(sqcow, argv[2])!=0) { + ddqcow.drv = &tapdisk_qcow; + ddqcow.private = malloc(ddqcow.drv->private_data_size); + + if (ddqcow.drv->td_open(&ddqcow, argv[2])!=0) { DFPRINTF("Unable to open Qcow file [%s]\n",argv[2]); exit(-1); } else DFPRINTF("QCOW file opened, size %llu\n", - (long long unsigned)sqcow->size); - - qcowio_fd = drv1->td_get_fd(sqcow); + (long long unsigned)ddqcow.td_state->size); + + qcowio_fd = ddqcow.io_fd; /*Setup aio destination file*/ ret = stat(argv[1],&finfo); @@ -191,12 +192,12 @@ int main(int argc, char *argv[]) argv[1], 0 - errno); exit(-1); } - if (ftruncate(fd, (off_t)sqcow->size<<9) < 0) { + if (ftruncate(fd, (off_t)ddqcow.td_state->size<<9) < 0) { DFPRINTF("Unable to create file " "[%s] of size %llu (errno %d). " "Exiting...\n", argv[1], - (long long unsigned)sqcow->size<<9, + (long long unsigned)ddqcow.td_state->size<<9, 0 - errno); close(fd); exit(-1); @@ -238,43 +239,43 @@ int main(int argc, char *argv[]) close(fd); exit(-1); } - if (size < sqcow->size<<9) { + if (size < ddqcow.td_state->size<<9) { DFPRINTF("ERROR: Not enough space on device " "%s (%lu bytes available, %llu bytes required\n", argv[1], size, - (long long unsigned)sqcow->size<<9); + (long long unsigned)ddqcow.td_state->size<<9); close(fd); exit(-1); } } else { - if (ftruncate(fd, (off_t)sqcow->size<<9) < 0) { + if (ftruncate(fd, (off_t)ddqcow.td_state->size<<9) < 0) { DFPRINTF("Unable to create file " "[%s] of size %llu (errno %d). " "Exiting...\n", argv[1], - (long long unsigned)sqcow->size<<9, + (long long unsigned)ddqcow.td_state->size<<9, 0 - errno); close(fd); exit(-1); } else DFPRINTF("File [%s] truncated to length %llu " "(%llu)\n", argv[1], - (long long unsigned)sqcow->size<<9, - (long long unsigned)sqcow->size); + (long long unsigned)ddqcow.td_state->size<<9, + (long long unsigned)ddqcow.td_state->size); } close(fd); } /*Open aio destination file*/ - drv2 = &tapdisk_aio; - saio->private = malloc(drv2->private_data_size); - - if (drv2->td_open(saio, argv[1])!=0) { + ddaio.drv = &tapdisk_aio; + ddaio.private = malloc(ddaio.drv->private_data_size); + + if (ddaio.drv->td_open(&ddaio, argv[1])!=0) { DFPRINTF("Unable to open Qcow file [%s]\n", argv[1]); exit(-1); } - aio_fd = drv2->td_get_fd(saio); + aio_fd = ddaio.io_fd; /*Initialise the output string*/ memset(output,0x20,25); @@ -298,9 +299,9 @@ int main(int argc, char *argv[]) } /*Attempt to read 4k sized blocks*/ - ret = drv1->td_queue_read(sqcow, i>>9, - BLOCK_PROCESSSZ>>9, buf, - send_read_responses, i>>9, buf); + ret = ddqcow.drv->td_queue_read(&ddqcow, i>>9, + BLOCK_PROCESSSZ>>9, buf, + send_read_responses, i>>9, buf); if (ret < 0) { DFPRINTF("UNABLE TO READ block [%llu]\n", @@ -311,12 +312,12 @@ int main(int argc, char *argv[]) submit_events++; } - if (i >= sqcow->size<<9) { + if (i >= ddqcow.td_state->size<<9) { complete = 1; } if ((submit_events % 10 == 0) || complete) - drv1->td_submit(sqcow); + ddqcow.drv->td_submit(&ddqcow); timeout.tv_usec = 0; } else { @@ -332,9 +333,9 @@ int main(int argc, char *argv[]) if (ret > 0) { if (FD_ISSET(qcowio_fd[0], &readfds)) - drv1->td_do_callbacks(sqcow, 0); + ddqcow.drv->td_do_callbacks(&ddqcow, 0); if (FD_ISSET(aio_fd[0], &readfds)) - drv2->td_do_callbacks(saio, 0); + ddaio.drv->td_do_callbacks(&ddaio, 0); } if (complete && (returned_write_events == submit_events)) running = 0; diff -r 04c23c1ef888 -r d907467f08cd tools/blktap/drivers/tapdisk.c --- a/tools/blktap/drivers/tapdisk.c Sun Feb 18 16:13:13 2007 -0700 +++ b/tools/blktap/drivers/tapdisk.c Tue Feb 20 12:58:22 2007 -0700 @@ -48,6 +48,12 @@ int connected_disks = 0; int connected_disks = 0; fd_list_entry_t *fd_start = NULL; +int do_cow_read(struct disk_driver *dd, blkif_request_t *req, + int sidx, uint64_t sector, int nr_secs); + +#define td_for_each_disk(tds, drv) \ + for (drv = tds->disks; drv != NULL; drv = drv->next) + void usage(void) { fprintf(stderr, "blktap-utils: v1.0.0\n"); @@ -78,10 +84,17 @@ static void unmap_disk(struct td_state * static void unmap_disk(struct td_state *s) { tapdev_info_t *info = s->ring_info; - struct tap_disk *drv = s->drv; + struct disk_driver *dd, *tmp; fd_list_entry_t *entry; - drv->td_close(s); + dd = s->disks; + while (dd) { + tmp = dd->next; + dd->drv->td_close(dd); + free(dd->private); + free(dd); + dd = tmp; + } if (info != NULL && info->mem > 0) munmap(info->mem, getpagesize() * BLKTAP_MMAP_REGION_SIZE); @@ -96,7 +109,6 @@ static void unmap_disk(struct td_state * free(s->fd_entry); free(s->blkif); free(s->ring_info); - free(s->private); free(s); return; @@ -113,16 +125,19 @@ static inline int LOCAL_FD_SET(fd_set *r static inline int LOCAL_FD_SET(fd_set *readfds) { fd_list_entry_t *ptr; + struct disk_driver *dd; ptr = fd_start; while (ptr != NULL) { if (ptr->tap_fd) { FD_SET(ptr->tap_fd, readfds); - if (ptr->io_fd[READ]) - FD_SET(ptr->io_fd[READ], readfds); - maxfds = (ptr->io_fd[READ] > maxfds ? - ptr->io_fd[READ]: maxfds); - maxfds = (ptr->tap_fd > maxfds ? ptr->tap_fd: maxfds); + td_for_each_disk(ptr->s, dd) { + if (dd->io_fd[READ]) + FD_SET(dd->io_fd[READ], readfds); + maxfds = (dd->io_fd[READ] > maxfds ? + dd->io_fd[READ] : maxfds); + } + maxfds = (ptr->tap_fd > maxfds ? ptr->tap_fd : maxfds); } ptr = ptr->next; } @@ -130,8 +145,7 @@ static inline int LOCAL_FD_SET(fd_set *r return 0; } -static inline fd_list_entry_t *add_fd_entry( - int tap_fd, int io_fd[MAX_IOFD], struct td_state *s) +static inline fd_list_entry_t *add_fd_entry(int tap_fd, struct td_state *s) { fd_list_entry_t **pprev, *entry; int i; @@ -139,12 +153,10 @@ static inline fd_list_entry_t *add_fd_en DPRINTF("Adding fd_list_entry\n"); /*Add to linked list*/ - s->fd_entry = entry = malloc(sizeof(fd_list_entry_t)); + s->fd_entry = entry = malloc(sizeof(fd_list_entry_t)); entry->tap_fd = tap_fd; - for (i = 0; i < MAX_IOFD; i++) - entry->io_fd[i] = io_fd[i]; - entry->s = s; - entry->next = NULL; + entry->s = s; + entry->next = NULL; pprev = &fd_start; while (*pprev != NULL) @@ -171,7 +183,7 @@ static struct tap_disk *get_driver(int d static struct tap_disk *get_driver(int drivertype) { /* blktapctrl has passed us the driver type */ - + return dtypes[drivertype]->drv; } @@ -183,12 +195,34 @@ static struct td_state *state_init(void) s = malloc(sizeof(struct td_state)); blkif = s->blkif = malloc(sizeof(blkif_t)); - s->ring_info = malloc(sizeof(tapdev_info_t)); - - for (i = 0; i < MAX_REQUESTS; i++) - blkif->pending_list[i].count = 0; + s->ring_info = calloc(1, sizeof(tapdev_info_t)); + + for (i = 0; i < MAX_REQUESTS; i++) { + blkif->pending_list[i].secs_pending = 0; + blkif->pending_list[i].submitting = 0; + } return s; +} + +static struct disk_driver *disk_init(struct td_state *s, struct tap_disk *drv) +{ + struct disk_driver *dd; + + dd = calloc(1, sizeof(struct disk_driver)); + if (!dd) + return NULL; + + dd->private = malloc(drv->private_data_size); + if (!dd->private) { + free(dd); + return NULL; + } + + dd->drv = drv; + dd->td_state = s; + + return dd; } static int map_new_dev(struct td_state *s, int minor) @@ -246,6 +280,51 @@ static int map_new_dev(struct td_state * return -1; } +static int open_disk(struct td_state *s, struct disk_driver *dd, char *path) +{ + int err; + struct disk_driver *d = dd; + + err = dd->drv->td_open(dd, path); + if (err) + return err; + + /* load backing files as necessary */ + while (d->drv->td_has_parent(d)) { + struct disk_driver *new; + + new = calloc(1, sizeof(struct disk_driver)); + if (!new) + goto fail; + new->drv = d->drv; + new->td_state = s; + new->private = malloc(new->drv->private_data_size); + if (!new->private) { + free(new); + goto fail; + } + + err = d->drv->td_get_parent(d, new); + if (err) + goto fail; + + d = d->next = new; + } + + return 0; + + fail: + DPRINTF("failed opening disk\n"); + while (dd) { + d = dd->next; + dd->drv->td_close(dd); + free(dd->private); + free(dd); + dd = d; + } + return err; +} + static int read_msg(char *buf) { int length, len, msglen, tap_fd, *io_fd; @@ -255,6 +334,7 @@ static int read_msg(char *buf) msg_newdev_t *msg_dev; msg_pid_t *msg_pid; struct tap_disk *drv; + struct disk_driver *dd; int ret = -1; struct td_state *s = NULL; fd_list_entry_t *entry; @@ -289,20 +369,20 @@ static int read_msg(char *buf) if (s == NULL) goto params_done; - s->drv = drv; - s->private = malloc(drv->private_data_size); - if (s->private == NULL) { + s->disks = dd = disk_init(s, drv); + if (!dd) { free(s); goto params_done; } /*Open file*/ - ret = drv->td_open(s, path); - io_fd = drv->td_get_fd(s); - - entry = add_fd_entry(0, io_fd, s); + ret = open_disk(s, dd, path); + if (ret) + goto params_done; + + entry = add_fd_entry(0, s); entry->cookie = msg->cookie; - DPRINTF("Entered cookie %d\n",entry->cookie); + DPRINTF("Entered cookie %d\n", entry->cookie); memset(buf, 0x00, MSG_SIZE); @@ -323,13 +403,12 @@ static int read_msg(char *buf) free(path); return 1; - - case CTLMSG_NEWDEV: msg_dev = (msg_newdev_t *)(buf + sizeof(msg_hdr_t)); s = get_state(msg->cookie); - DPRINTF("Retrieving state, cookie %d.....[%s]\n",msg->cookie, (s == NULL ? "FAIL":"OK")); + DPRINTF("Retrieving state, cookie %d.....[%s]\n", + msg->cookie, (s == NULL ? "FAIL":"OK")); if (s != NULL) { ret = ((map_new_dev(s, msg_dev->devnum) == msg_dev->devnum ? 0: -1)); @@ -397,49 +476,75 @@ static inline void kick_responses(struct } } -void io_done(struct td_state *s, int sid) -{ - struct tap_disk *drv = s->drv; +void io_done(struct disk_driver *dd, int sid) +{ + struct tap_disk *drv = dd->drv; if (!run) return; /*We have received signal to close*/ - if (drv->td_do_callbacks(s, sid) > 0) kick_responses(s); + if (drv->td_do_callbacks(dd, sid) > 0) kick_responses(dd->td_state); return; } -int send_responses(struct td_state *s, int res, int idx, void *private) -{ +static inline uint64_t +segment_start(blkif_request_t *req, int sidx) +{ + int i; + uint64_t start = req->sector_number; + + for (i = 0; i < sidx; i++) + start += (req->seg[i].last_sect - req->seg[i].first_sect + 1); + + return start; +} + +uint64_t sends, responds; +int send_responses(struct disk_driver *dd, int res, + uint64_t sector, int nr_secs, int idx, void *private) +{ + pending_req_t *preq; blkif_request_t *req; int responses_queued = 0; + struct td_state *s = dd->td_state; blkif_t *blkif = s->blkif; - - req = &blkif->pending_list[idx].req; - - if ( (idx > MAX_REQUESTS-1) || - (blkif->pending_list[idx].count == 0) ) + int sidx = (int)(long)private, secs_done = nr_secs; + + if ( (idx > MAX_REQUESTS-1) ) { DPRINTF("invalid index returned(%u)!\n", idx); return 0; } + preq = &blkif->pending_list[idx]; + req = &preq->req; + + if (res == BLK_NOT_ALLOCATED) { + res = do_cow_read(dd, req, sidx, sector, nr_secs); + if (res >= 0) { + secs_done = res; + res = 0; + } else + secs_done = 0; + } + + preq->secs_pending -= secs_done; + + if (res == -EBUSY && preq->submitting) + return -EBUSY; /* propagate -EBUSY back to higher layers */ + if (res) + preq->status = BLKIF_RSP_ERROR; - if (res != 0) { - blkif->pending_list[idx].status = BLKIF_RSP_ERROR; - } - - blkif->pending_list[idx].count--; - - if (blkif->pending_list[idx].count == 0) + if (!preq->submitting && preq->secs_pending == 0) { blkif_request_t tmp; blkif_response_t *rsp; - - tmp = blkif->pending_list[idx].req; + + tmp = preq->req; rsp = (blkif_response_t *)req; rsp->id = tmp.id; rsp->operation = tmp.operation; - rsp->status = blkif->pending_list[idx].status; + rsp->status = preq->status; write_rsp_to_ring(s, rsp); responses_queued++; @@ -447,15 +552,51 @@ int send_responses(struct td_state *s, i return responses_queued; } +int do_cow_read(struct disk_driver *dd, blkif_request_t *req, + int sidx, uint64_t sector, int nr_secs) +{ + char *page; + int ret, early; + uint64_t seg_start, seg_end; + struct td_state *s = dd->td_state; + tapdev_info_t *info = s->ring_info; + struct disk_driver *parent = dd->next; + + seg_start = segment_start(req, sidx); + seg_end = seg_start + req->seg[sidx].last_sect + 1; + + ASSERT(sector >= seg_start && sector + nr_secs <= seg_end); + + page = (char *)MMAP_VADDR(info->vstart, + (unsigned long)req->id, sidx); + page += (req->seg[sidx].first_sect << SECTOR_SHIFT); + page += ((sector - seg_start) << SECTOR_SHIFT); + + if (!parent) { + memset(page, 0, nr_secs << SECTOR_SHIFT); + return nr_secs; + } + + /* reissue request to backing file */ + ret = parent->drv->td_queue_read(parent, sector, nr_secs, + page, send_responses, + req->id, (void *)(long)sidx); + if (ret > 0) + parent->early += ret; + + return ((ret >= 0) ? 0 : ret); +} + static void get_io_request(struct td_state *s) { - RING_IDX rp, rc, j, i, ret; + RING_IDX rp, rc, j, i; blkif_request_t *req; - int idx, nsects; + int idx, nsects, ret; uint64_t sector_nr; char *page; int early = 0; /* count early completions */ - struct tap_disk *drv = s->drv; + struct disk_driver *dd = s->disks; + struct tap_disk *drv = dd->drv; blkif_t *blkif = s->blkif; tapdev_info_t *info = s->ring_info; int page_size = getpagesize(); @@ -466,23 +607,33 @@ static void get_io_request(struct td_sta rmb(); for (j = info->fe_ring.req_cons; j != rp; j++) { - int done = 0; + int done = 0, start_seg = 0; req = NULL; req = RING_GET_REQUEST(&info->fe_ring, j); ++info->fe_ring.req_cons; if (req == NULL) continue; - + idx = req->id; - ASSERT(blkif->pending_list[idx].count == 0); - memcpy(&blkif->pending_list[idx].req, req, sizeof(*req)); - blkif->pending_list[idx].status = BLKIF_RSP_OKAY; - blkif->pending_list[idx].count = req->nr_segments; - - sector_nr = req->sector_number; - - for (i = 0; i < req->nr_segments; i++) { + + if (info->busy.req) { + /* continue where we left off last time */ + ASSERT(info->busy.req == req); + start_seg = info->busy.seg_idx; + sector_nr = segment_start(req, start_seg); + info->busy.seg_idx = 0; + info->busy.req = NULL; + } else { + ASSERT(blkif->pending_list[idx].secs_pending == 0); + memcpy(&blkif->pending_list[idx].req, + req, sizeof(*req)); + blkif->pending_list[idx].status = BLKIF_RSP_OKAY; + blkif->pending_list[idx].submitting = 1; + sector_nr = req->sector_number; + } + + for (i = start_seg; i < req->nr_segments; i++) { nsects = req->seg[i].last_sect - req->seg[i].first_sect + 1; @@ -508,31 +659,37 @@ static void get_io_request(struct td_sta (long long unsigned) sector_nr); continue; } - + + blkif->pending_list[idx].secs_pending += nsects; + switch (req->operation) { case BLKIF_OP_WRITE: - ret = drv->td_queue_write(s, sector_nr, - nsects, page, send_responses, - idx, NULL); - if (ret > 0) early += ret; + ret = drv->td_queue_write(dd, sector_nr, + nsects, page, + send_responses, + idx, (void *)(long)i); + if (ret > 0) dd->early += ret; else if (ret == -EBUSY) { - /* - * TODO: Sector is locked * - * Need to put req back on queue * - */ + /* put req back on queue */ + --info->fe_ring.req_cons; + info->busy.req = req; + info->busy.seg_idx = i; + goto out; } break; case BLKIF_OP_READ: - ret = drv->td_queue_read(s, sector_nr, - nsects, page, send_responses, - idx, NULL); - if (ret > 0) early += ret; + ret = drv->td_queue_read(dd, sector_nr, + nsects, page, + send_responses, + idx, (void *)(long)i); + if (ret > 0) dd->early += ret; else if (ret == -EBUSY) { - /* - * TODO: Sector is locked * - * Need to put req back on queue * - */ + /* put req back on queue */ + --info->fe_ring.req_cons; + info->busy.req = req; + info->busy.seg_idx = i; + goto out; } break; default: @@ -541,14 +698,22 @@ static void get_io_request(struct td_sta } sector_nr += nsects; } - } - + blkif->pending_list[idx].submitting = 0; + /* force write_rsp_to_ring for synchronous case */ + if (blkif->pending_list[idx].secs_pending == 0) + dd->early += send_responses(dd, 0, 0, 0, idx, (void *)0); + } + + out: /*Batch done*/ - drv->td_submit(s); - - if (early > 0) - io_done(s,10); - + td_for_each_disk(s, dd) { + dd->early += dd->drv->td_submit(dd); + if (dd->early > 0) { + io_done(dd, 10); + dd->early = 0; + } + } + return; } @@ -558,10 +723,9 @@ int main(int argc, char *argv[]) char *p, *buf; fd_set readfds, writefds; fd_list_entry_t *ptr; - struct tap_disk *drv; struct td_state *s; char openlogbuf[128]; - + if (argc != 3) usage(); daemonize(); @@ -573,12 +737,12 @@ int main(int argc, char *argv[]) signal (SIGINT, sig_handler); /*Open the control channel*/ - fds[READ] = open(argv[1],O_RDWR|O_NONBLOCK); + fds[READ] = open(argv[1],O_RDWR|O_NONBLOCK); fds[WRITE] = open(argv[2],O_RDWR|O_NONBLOCK); if ( (fds[READ] < 0) || (fds[WRITE] < 0) ) { - DPRINTF("FD open failed [%d,%d]\n",fds[READ], fds[WRITE]); + DPRINTF("FD open failed [%d,%d]\n", fds[READ], fds[WRITE]); exit(-1); } @@ -608,11 +772,22 @@ int main(int argc, char *argv[]) { ptr = fd_start; while (ptr != NULL) { - if (FD_ISSET(ptr->tap_fd, &readfds)) + int progress_made = 0; + struct disk_driver *dd; + tapdev_info_t *info = ptr->s->ring_info; + + td_for_each_disk(ptr->s, dd) { + if (dd->io_fd[READ] && + FD_ISSET(dd->io_fd[READ], + &readfds)) { + io_done(dd, READ); + progress_made = 1; + } + } + + if (FD_ISSET(ptr->tap_fd, &readfds) || + (info->busy.req && progress_made)) get_io_request(ptr->s); - if (ptr->io_fd[READ] && - FD_ISSET(ptr->io_fd[READ], &readfds)) - io_done(ptr->s, READ); ptr = ptr->next; } @@ -628,11 +803,8 @@ int main(int argc, char *argv[]) ptr = fd_start; while (ptr != NULL) { s = ptr->s; - drv = s->drv; unmap_disk(s); - drv->td_close(s); - free(s->private); free(s->blkif); free(s->ring_info); free(s); diff -r 04c23c1ef888 -r d907467f08cd tools/blktap/drivers/tapdisk.h --- a/tools/blktap/drivers/tapdisk.h Sun Feb 18 16:13:13 2007 -0700 +++ b/tools/blktap/drivers/tapdisk.h Tue Feb 20 12:58:22 2007 -0700 @@ -43,6 +43,9 @@ * - The fd used for poll is an otherwise unused pipe, which allows poll to * be safely called without ever returning anything. * + * NOTE: tapdisk uses the number of sectors submitted per request as a + * ref count. Plugins must use the callback function to communicate the + * completion--or error--of every sector submitted to them. */ #ifndef TAPDISK_H_ @@ -65,39 +68,55 @@ #define SECTOR_SHIFT 9 #define DEFAULT_SECTOR_SIZE 512 +#define MAX_IOFD 2 + +#define BLK_NOT_ALLOCATED 99 + +struct td_state; +struct tap_disk; + +struct disk_driver { + int early; + void *private; + int io_fd[MAX_IOFD]; + struct tap_disk *drv; + struct td_state *td_state; + struct disk_driver *next; +}; + /* This structure represents the state of an active virtual disk. */ struct td_state { - void *private; - void *drv; + struct disk_driver *disks; void *blkif; void *image; void *ring_info; void *fd_entry; - char backing_file[1024]; /*Used by differencing disks, e.g. qcow*/ unsigned long sector_size; unsigned long long size; unsigned int info; }; /* Prototype of the callback to activate as requests complete. */ -typedef int (*td_callback_t)(struct td_state *s, int res, int id, void *prv); +typedef int (*td_callback_t)(struct disk_driver *dd, int res, uint64_t sector, + int nb_sectors, int id, void *private); /* Structure describing the interface to a virtual disk implementation. */ /* See note at the top of this file describing this interface. */ struct tap_disk { const char *disk_type; int private_data_size; - int (*td_open) (struct td_state *s, const char *name); - int (*td_queue_read) (struct td_state *s, uint64_t sector, - int nb_sectors, char *buf, td_callback_t cb, + int (*td_open) (struct disk_driver *dd, const char *name); + int (*td_queue_read) (struct disk_driver *dd, uint64_t sector, + int nb_sectors, char *buf, td_callback_t cb, int id, void *prv); - int (*td_queue_write) (struct td_state *s, uint64_t sector, - int nb_sectors, char *buf, td_callback_t cb, + int (*td_queue_write) (struct disk_driver *dd, uint64_t sector, + int nb_sectors, char *buf, td_callback_t cb, int id, void *prv); - int (*td_submit) (struct td_state *s); - int *(*td_get_fd) (struct td_state *s); - int (*td_close) (struct td_state *s); - int (*td_do_callbacks)(struct td_state *s, int sid); + int (*td_submit) (struct disk_driver *dd); + int (*td_has_parent) (struct disk_driver *dd); + int (*td_get_parent) (struct disk_driver *dd, struct disk_driver *p); + int (*td_close) (struct disk_driver *dd); + int (*td_do_callbacks)(struct disk_driver *dd, int sid); }; typedef struct disk_info { @@ -119,14 +138,13 @@ extern struct tap_disk tapdisk_ram; extern struct tap_disk tapdisk_ram; extern struct tap_disk tapdisk_qcow; -#define MAX_DISK_TYPES 20 -#define MAX_IOFD 2 - -#define DISK_TYPE_AIO 0 -#define DISK_TYPE_SYNC 1 -#define DISK_TYPE_VMDK 2 -#define DISK_TYPE_RAM 3 -#define DISK_TYPE_QCOW 4 +#define MAX_DISK_TYPES 20 + +#define DISK_TYPE_AIO 0 +#define DISK_TYPE_SYNC 1 +#define DISK_TYPE_VMDK 2 +#define DISK_TYPE_RAM 3 +#define DISK_TYPE_QCOW 4 /*Define Individual Disk Parameters here */ @@ -197,12 +215,10 @@ typedef struct fd_list_entry { typedef struct fd_list_entry { int cookie; int tap_fd; - int io_fd[MAX_IOFD]; struct td_state *s; struct fd_list_entry **pprev, *next; } fd_list_entry_t; int qcow_create(const char *filename, uint64_t total_size, const char *backing_file, int flags); - #endif /*TAPDISK_H_*/ diff -r 04c23c1ef888 -r d907467f08cd tools/blktap/lib/blktaplib.h --- a/tools/blktap/lib/blktaplib.h Sun Feb 18 16:13:13 2007 -0700 +++ b/tools/blktap/lib/blktaplib.h Tue Feb 20 12:58:22 2007 -0700 @@ -91,8 +91,9 @@ struct blkif; typedef struct { blkif_request_t req; - struct blkif *blkif; - int count; + struct blkif *blkif; + int submitting; + int secs_pending; int16_t status; } pending_req_t; @@ -116,7 +117,7 @@ typedef struct blkif { void *prv; /* device-specific data */ void *info; /*Image parameter passing */ - pending_req_t pending_list[MAX_REQUESTS]; + pending_req_t pending_list[MAX_REQUESTS]; int devnum; int fds[2]; int be_id; @@ -141,6 +142,11 @@ void free_blkif(blkif_t *blkif); void free_blkif(blkif_t *blkif); void __init_blkif(void); +typedef struct busy_state { + int seg_idx; + blkif_request_t *req; +} busy_state_t; + typedef struct tapdev_info { int fd; char *mem; @@ -148,6 +154,7 @@ typedef struct tapdev_info { blkif_back_ring_t fe_ring; unsigned long vstart; blkif_t *blkif; + busy_state_t busy; } tapdev_info_t; typedef struct domid_translate { diff -r 04c23c1ef888 -r d907467f08cd tools/blktap/lib/xs_api.c --- a/tools/blktap/lib/xs_api.c Sun Feb 18 16:13:13 2007 -0700 +++ b/tools/blktap/lib/xs_api.c Tue Feb 20 12:58:22 2007 -0700 @@ -311,8 +311,8 @@ int unregister_xenbus_watch(struct xs_ha } if (!xs_unwatch(h, watch->node, token)) - DPRINTF("XENBUS Failed to release watch %s: %i\n", - watch->node, er); + DPRINTF("XENBUS Failed to release watch %s\n", + watch->node); list_del(&watch->list); @@ -351,9 +351,9 @@ int xs_fire_next_watch(struct xs_handle node = res[XS_WATCH_PATH]; token = res[XS_WATCH_TOKEN]; - + w = find_watch(token); - if (w) + if (w) w->callback(h, w, node); free(res); diff -r 04c23c1ef888 -r d907467f08cd tools/check/check_zlib_lib --- a/tools/check/check_zlib_lib Sun Feb 18 16:13:13 2007 -0700 +++ b/tools/check/check_zlib_lib Tue Feb 20 12:58:22 2007 -0700 @@ -3,8 +3,10 @@ RC=0 +PATH=/sbin:$PATH + set -e -ldconfig -v 2>&1 | grep -q libz.so || RC=1 +ldconfig -p 2>&1 | grep -q libz.so || RC=1 if test ${RC} -ne 0; then echo diff -r 04c23c1ef888 -r d907467f08cd tools/console/daemon/io.c --- a/tools/console/daemon/io.c Sun Feb 18 16:13:13 2007 -0700 +++ b/tools/console/daemon/io.c Tue Feb 20 12:58:22 2007 -0700 @@ -63,6 +63,7 @@ struct domain char *conspath; int ring_ref; evtchn_port_t local_port; + evtchn_port_t remote_port; int xce_handle; struct xencons_interface *interface; }; @@ -234,6 +235,9 @@ static int domain_create_ring(struct dom if (err) goto out; + if ((ring_ref == dom->ring_ref) && (remote_port == dom->remote_port)) + goto out; + if (ring_ref != dom->ring_ref) { if (dom->interface != NULL) munmap(dom->interface, getpagesize()); @@ -249,6 +253,7 @@ static int domain_create_ring(struct dom } dom->local_port = -1; + dom->remote_port = -1; if (dom->xce_handle != -1) xc_evtchn_close(dom->xce_handle); @@ -270,6 +275,7 @@ static int domain_create_ring(struct dom goto out; } dom->local_port = rc; + dom->remote_port = remote_port; if (dom->tty_fd == -1) { dom->tty_fd = domain_create_tty(dom); @@ -279,6 +285,7 @@ static int domain_create_ring(struct dom xc_evtchn_close(dom->xce_handle); dom->xce_handle = -1; dom->local_port = -1; + dom->remote_port = -1; goto out; } } @@ -336,6 +343,7 @@ static struct domain *create_domain(int dom->ring_ref = -1; dom->local_port = -1; + dom->remote_port = -1; dom->interface = NULL; dom->xce_handle = -1; diff -r 04c23c1ef888 -r d907467f08cd tools/firmware/hvmloader/acpi/build.c --- a/tools/firmware/hvmloader/acpi/build.c Sun Feb 18 16:13:13 2007 -0700 +++ b/tools/firmware/hvmloader/acpi/build.c Tue Feb 20 12:58:22 2007 -0700 @@ -110,7 +110,9 @@ int construct_madt(struct acpi_20_madt * memset(lapic, 0, sizeof(*lapic)); lapic->type = ACPI_PROCESSOR_LOCAL_APIC; lapic->length = sizeof(*lapic); - lapic->acpi_processor_id = lapic->apic_id = LAPIC_ID(i); + /* Processor ID must match processor-object IDs in the DSDT. */ + lapic->acpi_processor_id = i; + lapic->apic_id = LAPIC_ID(i); lapic->flags = ACPI_LOCAL_APIC_ENABLED; offset += sizeof(*lapic); lapic++; @@ -144,6 +146,79 @@ int construct_hpet(struct acpi_20_hpet * return offset; } +int construct_processor_objects(uint8_t *buf) +{ + static const char pdat[13] = { 0x5b, 0x83, 0x0b, 0x50, 0x52 }; + static const char hex[] = "0123456789ABCDEF"; + unsigned int i, length, nr_cpus = get_vcpu_nr(); + struct acpi_header *hdr; + uint8_t *p = buf; + + /* + * 1. Table Header. + */ + + hdr = (struct acpi_header *)p; + hdr->signature = ASCII32('S','S','D','T'); + hdr->revision = 2; + strncpy(hdr->oem_id, ACPI_OEM_ID, 6); + strncpy(hdr->oem_table_id, ACPI_OEM_TABLE_ID, 8); + hdr->oem_revision = ACPI_OEM_REVISION; + hdr->creator_id = ACPI_CREATOR_ID; + hdr->creator_revision = ACPI_CREATOR_REVISION; + p += sizeof(*hdr); + + /* + * 2. Scope Definition. + */ + + /* ScopeOp */ + *p++ = 0x10; + + /* PkgLength (includes length bytes!). */ + length = 1 + 5 + (nr_cpus * sizeof(pdat)); + if ( length <= 0x3f ) + { + *p++ = length; + } + else if ( ++length <= 0xfff ) + { + *p++ = 0x40 | (length & 0xf); + *p++ = length >> 4; + } + else + { + length++; + *p++ = 0x80 | (length & 0xf); + *p++ = (length >> 4) & 0xff; + *p++ = (length >> 12) & 0xff; + } + + /* NameString */ + strncpy(p, "\\_PR_", 5); + p += 5; + + /* + * 3. Processor Objects. + */ + + for ( i = 0; i < nr_cpus; i++ ) + { + memcpy(p, pdat, sizeof(pdat)); + /* ProcessorName */ + p[5] = hex[(i>>4)&15]; + p[6] = hex[(i>>0)&15]; + /* ProcessorID */ + p[7] = i; + p += sizeof(pdat); + } + + hdr->length = p - buf; + set_checksum(hdr, offsetof(struct acpi_header, checksum), hdr->length); + + return hdr->length; +} + int construct_secondary_tables(uint8_t *buf, unsigned long *table_ptrs) { int offset = 0, nr_tables = 0; @@ -165,6 +240,10 @@ int construct_secondary_tables(uint8_t * hpet = (struct acpi_20_hpet *)&buf[offset]; offset += construct_hpet(hpet); table_ptrs[nr_tables++] = (unsigned long)hpet; + + /* Processor Object SSDT. */ + table_ptrs[nr_tables++] = (unsigned long)&buf[offset]; + offset += construct_processor_objects(&buf[offset]); /* TPM TCPA and SSDT. */ tis_hdr = (uint16_t *)0xFED40F00; diff -r 04c23c1ef888 -r d907467f08cd tools/firmware/hvmloader/acpi/dsdt.asl --- a/tools/firmware/hvmloader/acpi/dsdt.asl Sun Feb 18 16:13:13 2007 -0700 +++ b/tools/firmware/hvmloader/acpi/dsdt.asl Tue Feb 20 12:58:22 2007 -0700 @@ -27,14 +27,6 @@ DefinitionBlock ("DSDT.aml", "DSDT", 2, Name (\APCL, 0x00010000) Name (\PUID, 0x00) - Scope (\_PR) - { - Processor (CPU0, 0x00, 0x00000000, 0x00) {} - Processor (CPU1, 0x01, 0x00000000, 0x00) {} - Processor (CPU2, 0x02, 0x00000000, 0x00) {} - Processor (CPU3, 0x03, 0x00000000, 0x00) {} - } - /* Poweroff support - ties in with qemu emulation */ Name (\_S5, Package (0x04) { diff -r 04c23c1ef888 -r d907467f08cd tools/firmware/hvmloader/acpi/dsdt.c --- a/tools/firmware/hvmloader/acpi/dsdt.c Sun Feb 18 16:13:13 2007 -0700 +++ b/tools/firmware/hvmloader/acpi/dsdt.c Tue Feb 20 12:58:22 2007 -0700 @@ -1,19 +1,19 @@ /* * * Intel ACPI Component Architecture - * ASL Optimizing Compiler version 20060707 [Dec 30 2006] + * ASL Optimizing Compiler version 20060707 [Feb 16 2007] * Copyright (C) 2000 - 2006 Intel Corporation * Supports ACPI Specification Revision 3.0a * - * Compilation of "dsdt.asl" - Sat Dec 30 15:31:23 2006 + * Compilation of "dsdt.asl" - Fri Feb 16 15:14:37 2007 * * C source code output * */ unsigned char AmlCode[] = { - 0x44,0x53,0x44,0x54,0xD9,0x0D,0x00,0x00, /* 00000000 "DSDT...." */ - 0x02,0xFB,0x58,0x65,0x6E,0x00,0x00,0x00, /* 00000008 "..Xen..." */ + 0x44,0x53,0x44,0x54,0x9F,0x0D,0x00,0x00, /* 00000000 "DSDT...." */ + 0x02,0xEE,0x58,0x65,0x6E,0x00,0x00,0x00, /* 00000008 "..Xen..." */ 0x48,0x56,0x4D,0x00,0x00,0x00,0x00,0x00, /* 00000010 "HVM....." */ 0x00,0x00,0x00,0x00,0x49,0x4E,0x54,0x4C, /* 00000018 "....INTL" */ 0x07,0x07,0x06,0x20,0x08,0x50,0x4D,0x42, /* 00000020 "... .PMB" */ @@ -23,438 +23,430 @@ unsigned char AmlCode[] = 0x41,0x50,0x43,0x42,0x0C,0x00,0x00,0xC0, /* 00000040 "APCB...." */ 0xFE,0x08,0x41,0x50,0x43,0x4C,0x0C,0x00, /* 00000048 "..APCL.." */ 0x00,0x01,0x00,0x08,0x50,0x55,0x49,0x44, /* 00000050 "....PUID" */ - 0x00,0x10,0x39,0x5F,0x50,0x52,0x5F,0x5B, /* 00000058 "..9_PR_[" */ - 0x83,0x0B,0x43,0x50,0x55,0x30,0x00,0x00, /* 00000060 "..CPU0.." */ - 0x00,0x00,0x00,0x00,0x5B,0x83,0x0B,0x43, /* 00000068 "....[..C" */ - 0x50,0x55,0x31,0x01,0x00,0x00,0x00,0x00, /* 00000070 "PU1....." */ - 0x00,0x5B,0x83,0x0B,0x43,0x50,0x55,0x32, /* 00000078 ".[..CPU2" */ - 0x02,0x00,0x00,0x00,0x00,0x00,0x5B,0x83, /* 00000080 "......[." */ - 0x0B,0x43,0x50,0x55,0x33,0x03,0x00,0x00, /* 00000088 ".CPU3..." */ - 0x00,0x00,0x00,0x08,0x5F,0x53,0x35,0x5F, /* 00000090 "...._S5_" */ - 0x12,0x08,0x04,0x0A,0x07,0x0A,0x07,0x00, /* 00000098 "........" */ - 0x00,0x08,0x50,0x49,0x43,0x44,0x00,0x14, /* 000000A0 "..PICD.." */ - 0x0C,0x5F,0x50,0x49,0x43,0x01,0x70,0x68, /* 000000A8 "._PIC.ph" */ - 0x50,0x49,0x43,0x44,0x10,0x44,0xD2,0x5F, /* 000000B0 "PICD.D._" */ - 0x53,0x42,0x5F,0x5B,0x82,0x49,0x04,0x4D, /* 000000B8 "SB_[.I.M" */ - 0x45,0x4D,0x30,0x08,0x5F,0x48,0x49,0x44, /* 000000C0 "EM0._HID" */ - 0x0C,0x41,0xD0,0x0C,0x02,0x08,0x5F,0x43, /* 000000C8 ".A...._C" */ - 0x52,0x53,0x11,0x33,0x0A,0x30,0x8A,0x2B, /* 000000D0 "RS.3.0.+" */ - 0x00,0x00,0x0D,0x03,0x00,0x00,0x00,0x00, /* 000000D8 "........" */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 000000E0 "........" */ - 0x00,0x00,0x00,0x00,0xFF,0xFF,0x09,0x00, /* 000000E8 "........" */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 000000F0 "........" */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x0A,0x00, /* 000000F8 "........" */ - 0x00,0x00,0x00,0x00,0x79,0x00,0x5B,0x82, /* 00000100 "....y.[." */ - 0x41,0xCD,0x50,0x43,0x49,0x30,0x08,0x5F, /* 00000108 "A.PCI0._" */ - 0x48,0x49,0x44,0x0C,0x41,0xD0,0x0A,0x03, /* 00000110 "HID.A..." */ - 0x08,0x5F,0x55,0x49,0x44,0x00,0x08,0x5F, /* 00000118 "._UID.._" */ - 0x41,0x44,0x52,0x00,0x08,0x5F,0x42,0x42, /* 00000120 "ADR.._BB" */ - 0x4E,0x00,0x14,0x44,0x08,0x5F,0x43,0x52, /* 00000128 "N..D._CR" */ - 0x53,0x00,0x08,0x50,0x52,0x54,0x30,0x11, /* 00000130 "S..PRT0." */ - 0x42,0x07,0x0A,0x6E,0x88,0x0D,0x00,0x02, /* 00000138 "B..n...." */ - 0x0F,0x00,0x00,0x00,0x00,0x00,0xFF,0x00, /* 00000140 "........" */ - 0x00,0x00,0x00,0x01,0x47,0x01,0xF8,0x0C, /* 00000148 "....G..." */ - 0xF8,0x0C,0x01,0x08,0x88,0x0D,0x00,0x01, /* 00000150 "........" */ - 0x0C,0x03,0x00,0x00,0x00,0x00,0xF7,0x0C, /* 00000158 "........" */ - 0x00,0x00,0xF8,0x0C,0x88,0x0D,0x00,0x01, /* 00000160 "........" */ - 0x0C,0x03,0x00,0x00,0x00,0x0D,0xFF,0xFF, /* 00000168 "........" */ - 0x00,0x00,0x00,0xF3,0x87,0x17,0x00,0x00, /* 00000170 "........" */ - 0x0C,0x03,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000178 "........" */ - 0x0A,0x00,0xFF,0xFF,0x0B,0x00,0x00,0x00, /* 00000180 "........" */ - 0x00,0x00,0x00,0x00,0x02,0x00,0x87,0x17, /* 00000188 "........" */ - 0x00,0x00,0x0D,0x03,0x00,0x00,0x00,0x00, /* 00000190 "........" */ - 0x00,0x00,0x00,0xF0,0xFF,0xFF,0xFF,0xF4, /* 00000198 "........" */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05, /* 000001A0 "........" */ - 0x79,0x00,0xA4,0x50,0x52,0x54,0x30,0x08, /* 000001A8 "y..PRT0." */ - 0x42,0x55,0x46,0x41,0x11,0x09,0x0A,0x06, /* 000001B0 "BUFA...." */ - 0x23,0x60,0x0C,0x18,0x79,0x00,0x08,0x42, /* 000001B8 "#`..y..B" */ - 0x55,0x46,0x42,0x11,0x09,0x0A,0x06,0x23, /* 000001C0 "UFB....#" */ - 0x00,0x00,0x18,0x79,0x00,0x8B,0x42,0x55, /* 000001C8 "...y..BU" */ - 0x46,0x42,0x01,0x49,0x52,0x51,0x56,0x5B, /* 000001D0 "FB.IRQV[" */ - 0x82,0x48,0x08,0x4C,0x4E,0x4B,0x41,0x08, /* 000001D8 ".H.LNKA." */ - 0x5F,0x48,0x49,0x44,0x0C,0x41,0xD0,0x0C, /* 000001E0 "_HID.A.." */ - 0x0F,0x08,0x5F,0x55,0x49,0x44,0x01,0x14, /* 000001E8 ".._UID.." */ - 0x1C,0x5F,0x53,0x54,0x41,0x00,0x7B,0x50, /* 000001F0 "._STA.{P" */ - 0x49,0x52,0x41,0x0A,0x80,0x60,0xA0,0x08, /* 000001F8 "IRA..`.." */ - 0x93,0x60,0x0A,0x80,0xA4,0x0A,0x09,0xA1, /* 00000200 ".`......" */ - 0x04,0xA4,0x0A,0x0B,0x14,0x0B,0x5F,0x50, /* 00000208 "......_P" */ - 0x52,0x53,0x00,0xA4,0x42,0x55,0x46,0x41, /* 00000210 "RS..BUFA" */ - 0x14,0x11,0x5F,0x44,0x49,0x53,0x00,0x7D, /* 00000218 ".._DIS.}" */ - 0x50,0x49,0x52,0x41,0x0A,0x80,0x50,0x49, /* 00000220 "PIRA..PI" */ - 0x52,0x41,0x14,0x1A,0x5F,0x43,0x52,0x53, /* 00000228 "RA.._CRS" */ - 0x00,0x7B,0x50,0x49,0x52,0x41,0x0A,0x0F, /* 00000230 ".{PIRA.." */ - 0x60,0x79,0x01,0x60,0x49,0x52,0x51,0x56, /* 00000238 "`y.`IRQV" */ - 0xA4,0x42,0x55,0x46,0x42,0x14,0x1B,0x5F, /* 00000240 ".BUFB.._" */ - 0x53,0x52,0x53,0x01,0x8B,0x68,0x01,0x49, /* 00000248 "SRS..h.I" */ - 0x52,0x51,0x31,0x82,0x49,0x52,0x51,0x31, /* 00000250 "RQ1.IRQ1" */ - 0x60,0x76,0x60,0x70,0x60,0x50,0x49,0x52, /* 00000258 "`v`p`PIR" */ - 0x41,0x5B,0x82,0x49,0x08,0x4C,0x4E,0x4B, /* 00000260 "A[.I.LNK" */ - 0x42,0x08,0x5F,0x48,0x49,0x44,0x0C,0x41, /* 00000268 "B._HID.A" */ - 0xD0,0x0C,0x0F,0x08,0x5F,0x55,0x49,0x44, /* 00000270 "...._UID" */ - 0x0A,0x02,0x14,0x1C,0x5F,0x53,0x54,0x41, /* 00000278 "...._STA" */ - 0x00,0x7B,0x50,0x49,0x52,0x42,0x0A,0x80, /* 00000280 ".{PIRB.." */ - 0x60,0xA0,0x08,0x93,0x60,0x0A,0x80,0xA4, /* 00000288 "`...`..." */ - 0x0A,0x09,0xA1,0x04,0xA4,0x0A,0x0B,0x14, /* 00000290 "........" */ - 0x0B,0x5F,0x50,0x52,0x53,0x00,0xA4,0x42, /* 00000298 "._PRS..B" */ - 0x55,0x46,0x41,0x14,0x11,0x5F,0x44,0x49, /* 000002A0 "UFA.._DI" */ - 0x53,0x00,0x7D,0x50,0x49,0x52,0x42,0x0A, /* 000002A8 "S.}PIRB." */ - 0x80,0x50,0x49,0x52,0x42,0x14,0x1A,0x5F, /* 000002B0 ".PIRB.._" */ - 0x43,0x52,0x53,0x00,0x7B,0x50,0x49,0x52, /* 000002B8 "CRS.{PIR" */ - 0x42,0x0A,0x0F,0x60,0x79,0x01,0x60,0x49, /* 000002C0 "B..`y.`I" */ - 0x52,0x51,0x56,0xA4,0x42,0x55,0x46,0x42, /* 000002C8 "RQV.BUFB" */ - 0x14,0x1B,0x5F,0x53,0x52,0x53,0x01,0x8B, /* 000002D0 ".._SRS.." */ - 0x68,0x01,0x49,0x52,0x51,0x31,0x82,0x49, /* 000002D8 "h.IRQ1.I" */ - 0x52,0x51,0x31,0x60,0x76,0x60,0x70,0x60, /* 000002E0 "RQ1`v`p`" */ - 0x50,0x49,0x52,0x42,0x5B,0x82,0x49,0x08, /* 000002E8 "PIRB[.I." */ - 0x4C,0x4E,0x4B,0x43,0x08,0x5F,0x48,0x49, /* 000002F0 "LNKC._HI" */ - 0x44,0x0C,0x41,0xD0,0x0C,0x0F,0x08,0x5F, /* 000002F8 "D.A...._" */ - 0x55,0x49,0x44,0x0A,0x03,0x14,0x1C,0x5F, /* 00000300 "UID...._" */ - 0x53,0x54,0x41,0x00,0x7B,0x50,0x49,0x52, /* 00000308 "STA.{PIR" */ - 0x43,0x0A,0x80,0x60,0xA0,0x08,0x93,0x60, /* 00000310 "C..`...`" */ - 0x0A,0x80,0xA4,0x0A,0x09,0xA1,0x04,0xA4, /* 00000318 "........" */ - 0x0A,0x0B,0x14,0x0B,0x5F,0x50,0x52,0x53, /* 00000320 "...._PRS" */ - 0x00,0xA4,0x42,0x55,0x46,0x41,0x14,0x11, /* 00000328 "..BUFA.." */ - 0x5F,0x44,0x49,0x53,0x00,0x7D,0x50,0x49, /* 00000330 "_DIS.}PI" */ - 0x52,0x43,0x0A,0x80,0x50,0x49,0x52,0x43, /* 00000338 "RC..PIRC" */ - 0x14,0x1A,0x5F,0x43,0x52,0x53,0x00,0x7B, /* 00000340 ".._CRS.{" */ - 0x50,0x49,0x52,0x43,0x0A,0x0F,0x60,0x79, /* 00000348 "PIRC..`y" */ - 0x01,0x60,0x49,0x52,0x51,0x56,0xA4,0x42, /* 00000350 ".`IRQV.B" */ - 0x55,0x46,0x42,0x14,0x1B,0x5F,0x53,0x52, /* 00000358 "UFB.._SR" */ - 0x53,0x01,0x8B,0x68,0x01,0x49,0x52,0x51, /* 00000360 "S..h.IRQ" */ - 0x31,0x82,0x49,0x52,0x51,0x31,0x60,0x76, /* 00000368 "1.IRQ1`v" */ - 0x60,0x70,0x60,0x50,0x49,0x52,0x43,0x5B, /* 00000370 "`p`PIRC[" */ - 0x82,0x49,0x08,0x4C,0x4E,0x4B,0x44,0x08, /* 00000378 ".I.LNKD." */ - 0x5F,0x48,0x49,0x44,0x0C,0x41,0xD0,0x0C, /* 00000380 "_HID.A.." */ - 0x0F,0x08,0x5F,0x55,0x49,0x44,0x0A,0x04, /* 00000388 ".._UID.." */ - 0x14,0x1C,0x5F,0x53,0x54,0x41,0x00,0x7B, /* 00000390 ".._STA.{" */ - 0x50,0x49,0x52,0x44,0x0A,0x80,0x60,0xA0, /* 00000398 "PIRD..`." */ - 0x08,0x93,0x60,0x0A,0x80,0xA4,0x0A,0x09, /* 000003A0 "..`....." */ - 0xA1,0x04,0xA4,0x0A,0x0B,0x14,0x0B,0x5F, /* 000003A8 "......._" */ - 0x50,0x52,0x53,0x00,0xA4,0x42,0x55,0x46, /* 000003B0 "PRS..BUF" */ - 0x41,0x14,0x11,0x5F,0x44,0x49,0x53,0x00, /* 000003B8 "A.._DIS." */ - 0x7D,0x50,0x49,0x52,0x44,0x0A,0x80,0x50, /* 000003C0 "}PIRD..P" */ - 0x49,0x52,0x44,0x14,0x1A,0x5F,0x43,0x52, /* 000003C8 "IRD.._CR" */ - 0x53,0x00,0x7B,0x50,0x49,0x52,0x44,0x0A, /* 000003D0 "S.{PIRD." */ - 0x0F,0x60,0x79,0x01,0x60,0x49,0x52,0x51, /* 000003D8 ".`y.`IRQ" */ - 0x56,0xA4,0x42,0x55,0x46,0x42,0x14,0x1B, /* 000003E0 "V.BUFB.." */ - 0x5F,0x53,0x52,0x53,0x01,0x8B,0x68,0x01, /* 000003E8 "_SRS..h." */ - 0x49,0x52,0x51,0x31,0x82,0x49,0x52,0x51, /* 000003F0 "IRQ1.IRQ" */ - 0x31,0x60,0x76,0x60,0x70,0x60,0x50,0x49, /* 000003F8 "1`v`p`PI" */ - 0x52,0x44,0x5B,0x82,0x3A,0x48,0x50,0x45, /* 00000400 "RD[.:HPE" */ - 0x54,0x08,0x5F,0x48,0x49,0x44,0x0C,0x41, /* 00000408 "T._HID.A" */ - 0xD0,0x01,0x03,0x08,0x5F,0x55,0x49,0x44, /* 00000410 "...._UID" */ - 0x00,0x08,0x5F,0x43,0x52,0x53,0x11,0x1F, /* 00000418 ".._CRS.." */ - 0x0A,0x1C,0x87,0x17,0x00,0x00,0x0D,0x01, /* 00000420 "........" */ - 0x00,0x00,0x00,0x00,0x00,0x00,0xD0,0xFE, /* 00000428 "........" */ - 0xFF,0x03,0xD0,0xFE,0x00,0x00,0x00,0x00, /* 00000430 "........" */ - 0x00,0x04,0x00,0x00,0x79,0x00,0x14,0x16, /* 00000438 "....y..." */ - 0x5F,0x50,0x52,0x54,0x00,0xA0,0x0A,0x50, /* 00000440 "_PRT...P" */ - 0x49,0x43,0x44,0xA4,0x50,0x52,0x54,0x41, /* 00000448 "ICD.PRTA" */ - 0xA4,0x50,0x52,0x54,0x50,0x08,0x50,0x52, /* 00000450 ".PRTP.PR" */ - 0x54,0x50,0x12,0x49,0x36,0x3C,0x12,0x0D, /* 00000458 "TP.I6<.." */ - 0x04,0x0C,0xFF,0xFF,0x01,0x00,0x00,0x4C, /* 00000460 ".......L" */ - 0x4E,0x4B,0x42,0x00,0x12,0x0D,0x04,0x0C, /* 00000468 "NKB....." */ - 0xFF,0xFF,0x01,0x00,0x01,0x4C,0x4E,0x4B, /* 00000470 ".....LNK" */ - 0x43,0x00,0x12,0x0E,0x04,0x0C,0xFF,0xFF, /* 00000478 "C......." */ - 0x01,0x00,0x0A,0x02,0x4C,0x4E,0x4B,0x44, /* 00000480 "....LNKD" */ - 0x00,0x12,0x0E,0x04,0x0C,0xFF,0xFF,0x01, /* 00000488 "........" */ - 0x00,0x0A,0x03,0x4C,0x4E,0x4B,0x41,0x00, /* 00000490 "...LNKA." */ - 0x12,0x0D,0x04,0x0C,0xFF,0xFF,0x02,0x00, /* 00000498 "........" */ - 0x00,0x4C,0x4E,0x4B,0x43,0x00,0x12,0x0D, /* 000004A0 ".LNKC..." */ - 0x04,0x0C,0xFF,0xFF,0x02,0x00,0x01,0x4C, /* 000004A8 ".......L" */ - 0x4E,0x4B,0x44,0x00,0x12,0x0E,0x04,0x0C, /* 000004B0 "NKD....." */ - 0xFF,0xFF,0x02,0x00,0x0A,0x02,0x4C,0x4E, /* 000004B8 "......LN" */ - 0x4B,0x41,0x00,0x12,0x0E,0x04,0x0C,0xFF, /* 000004C0 "KA......" */ - 0xFF,0x02,0x00,0x0A,0x03,0x4C,0x4E,0x4B, /* 000004C8 ".....LNK" */ - 0x42,0x00,0x12,0x0D,0x04,0x0C,0xFF,0xFF, /* 000004D0 "B......." */ - 0x03,0x00,0x00,0x4C,0x4E,0x4B,0x44,0x00, /* 000004D8 "...LNKD." */ - 0x12,0x0D,0x04,0x0C,0xFF,0xFF,0x03,0x00, /* 000004E0 "........" */ - 0x01,0x4C,0x4E,0x4B,0x41,0x00,0x12,0x0E, /* 000004E8 ".LNKA..." */ - 0x04,0x0C,0xFF,0xFF,0x03,0x00,0x0A,0x02, /* 000004F0 "........" */ - 0x4C,0x4E,0x4B,0x42,0x00,0x12,0x0E,0x04, /* 000004F8 "LNKB...." */ - 0x0C,0xFF,0xFF,0x03,0x00,0x0A,0x03,0x4C, /* 00000500 ".......L" */ - 0x4E,0x4B,0x43,0x00,0x12,0x0D,0x04,0x0C, /* 00000508 "NKC....." */ - 0xFF,0xFF,0x04,0x00,0x00,0x4C,0x4E,0x4B, /* 00000510 ".....LNK" */ - 0x41,0x00,0x12,0x0D,0x04,0x0C,0xFF,0xFF, /* 00000518 "A......." */ - 0x04,0x00,0x01,0x4C,0x4E,0x4B,0x42,0x00, /* 00000520 "...LNKB." */ - 0x12,0x0E,0x04,0x0C,0xFF,0xFF,0x04,0x00, /* 00000528 "........" */ - 0x0A,0x02,0x4C,0x4E,0x4B,0x43,0x00,0x12, /* 00000530 "..LNKC.." */ - 0x0E,0x04,0x0C,0xFF,0xFF,0x04,0x00,0x0A, /* 00000538 "........" */ - 0x03,0x4C,0x4E,0x4B,0x44,0x00,0x12,0x0D, /* 00000540 ".LNKD..." */ - 0x04,0x0C,0xFF,0xFF,0x05,0x00,0x00,0x4C, /* 00000548 ".......L" */ - 0x4E,0x4B,0x42,0x00,0x12,0x0D,0x04,0x0C, /* 00000550 "NKB....." */ - 0xFF,0xFF,0x05,0x00,0x01,0x4C,0x4E,0x4B, /* 00000558 ".....LNK" */ - 0x43,0x00,0x12,0x0E,0x04,0x0C,0xFF,0xFF, /* 00000560 "C......." */ - 0x05,0x00,0x0A,0x02,0x4C,0x4E,0x4B,0x44, /* 00000568 "....LNKD" */ - 0x00,0x12,0x0E,0x04,0x0C,0xFF,0xFF,0x05, /* 00000570 "........" */ - 0x00,0x0A,0x03,0x4C,0x4E,0x4B,0x41,0x00, /* 00000578 "...LNKA." */ - 0x12,0x0D,0x04,0x0C,0xFF,0xFF,0x06,0x00, /* 00000580 "........" */ - 0x00,0x4C,0x4E,0x4B,0x43,0x00,0x12,0x0D, /* 00000588 ".LNKC..." */ - 0x04,0x0C,0xFF,0xFF,0x06,0x00,0x01,0x4C, /* 00000590 ".......L" */ - 0x4E,0x4B,0x44,0x00,0x12,0x0E,0x04,0x0C, /* 00000598 "NKD....." */ - 0xFF,0xFF,0x06,0x00,0x0A,0x02,0x4C,0x4E, /* 000005A0 "......LN" */ - 0x4B,0x41,0x00,0x12,0x0E,0x04,0x0C,0xFF, /* 000005A8 "KA......" */ - 0xFF,0x06,0x00,0x0A,0x03,0x4C,0x4E,0x4B, /* 000005B0 ".....LNK" */ - 0x42,0x00,0x12,0x0D,0x04,0x0C,0xFF,0xFF, /* 000005B8 "B......." */ - 0x07,0x00,0x00,0x4C,0x4E,0x4B,0x44,0x00, /* 000005C0 "...LNKD." */ - 0x12,0x0D,0x04,0x0C,0xFF,0xFF,0x07,0x00, /* 000005C8 "........" */ - 0x01,0x4C,0x4E,0x4B,0x41,0x00,0x12,0x0E, /* 000005D0 ".LNKA..." */ - 0x04,0x0C,0xFF,0xFF,0x07,0x00,0x0A,0x02, /* 000005D8 "........" */ - 0x4C,0x4E,0x4B,0x42,0x00,0x12,0x0E,0x04, /* 000005E0 "LNKB...." */ - 0x0C,0xFF,0xFF,0x07,0x00,0x0A,0x03,0x4C, /* 000005E8 ".......L" */ - 0x4E,0x4B,0x43,0x00,0x12,0x0D,0x04,0x0C, /* 000005F0 "NKC....." */ - 0xFF,0xFF,0x08,0x00,0x00,0x4C,0x4E,0x4B, /* 000005F8 ".....LNK" */ - 0x41,0x00,0x12,0x0D,0x04,0x0C,0xFF,0xFF, /* 00000600 "A......." */ - 0x08,0x00,0x01,0x4C,0x4E,0x4B,0x42,0x00, /* 00000608 "...LNKB." */ - 0x12,0x0E,0x04,0x0C,0xFF,0xFF,0x08,0x00, /* 00000610 "........" */ - 0x0A,0x02,0x4C,0x4E,0x4B,0x43,0x00,0x12, /* 00000618 "..LNKC.." */ - 0x0E,0x04,0x0C,0xFF,0xFF,0x08,0x00,0x0A, /* 00000620 "........" */ - 0x03,0x4C,0x4E,0x4B,0x44,0x00,0x12,0x0D, /* 00000628 ".LNKD..." */ - 0x04,0x0C,0xFF,0xFF,0x09,0x00,0x00,0x4C, /* 00000630 ".......L" */ - 0x4E,0x4B,0x42,0x00,0x12,0x0D,0x04,0x0C, /* 00000638 "NKB....." */ - 0xFF,0xFF,0x09,0x00,0x01,0x4C,0x4E,0x4B, /* 00000640 ".....LNK" */ - 0x43,0x00,0x12,0x0E,0x04,0x0C,0xFF,0xFF, /* 00000648 "C......." */ - 0x09,0x00,0x0A,0x02,0x4C,0x4E,0x4B,0x44, /* 00000650 "....LNKD" */ - 0x00,0x12,0x0E,0x04,0x0C,0xFF,0xFF,0x09, /* 00000658 "........" */ - 0x00,0x0A,0x03,0x4C,0x4E,0x4B,0x41,0x00, /* 00000660 "...LNKA." */ - 0x12,0x0D,0x04,0x0C,0xFF,0xFF,0x0A,0x00, /* 00000668 "........" */ - 0x00,0x4C,0x4E,0x4B,0x43,0x00,0x12,0x0D, /* 00000670 ".LNKC..." */ - 0x04,0x0C,0xFF,0xFF,0x0A,0x00,0x01,0x4C, /* 00000678 ".......L" */ - 0x4E,0x4B,0x44,0x00,0x12,0x0E,0x04,0x0C, /* 00000680 "NKD....." */ - 0xFF,0xFF,0x0A,0x00,0x0A,0x02,0x4C,0x4E, /* 00000688 "......LN" */ - 0x4B,0x41,0x00,0x12,0x0E,0x04,0x0C,0xFF, /* 00000690 "KA......" */ - 0xFF,0x0A,0x00,0x0A,0x03,0x4C,0x4E,0x4B, /* 00000698 ".....LNK" */ - 0x42,0x00,0x12,0x0D,0x04,0x0C,0xFF,0xFF, /* 000006A0 "B......." */ - 0x0B,0x00,0x00,0x4C,0x4E,0x4B,0x44,0x00, /* 000006A8 "...LNKD." */ - 0x12,0x0D,0x04,0x0C,0xFF,0xFF,0x0B,0x00, /* 000006B0 "........" */ - 0x01,0x4C,0x4E,0x4B,0x41,0x00,0x12,0x0E, /* 000006B8 ".LNKA..." */ - 0x04,0x0C,0xFF,0xFF,0x0B,0x00,0x0A,0x02, /* 000006C0 "........" */ - 0x4C,0x4E,0x4B,0x42,0x00,0x12,0x0E,0x04, /* 000006C8 "LNKB...." */ - 0x0C,0xFF,0xFF,0x0B,0x00,0x0A,0x03,0x4C, /* 000006D0 ".......L" */ - 0x4E,0x4B,0x43,0x00,0x12,0x0D,0x04,0x0C, /* 000006D8 "NKC....." */ - 0xFF,0xFF,0x0C,0x00,0x00,0x4C,0x4E,0x4B, /* 000006E0 ".....LNK" */ - 0x41,0x00,0x12,0x0D,0x04,0x0C,0xFF,0xFF, /* 000006E8 "A......." */ - 0x0C,0x00,0x01,0x4C,0x4E,0x4B,0x42,0x00, /* 000006F0 "...LNKB." */ - 0x12,0x0E,0x04,0x0C,0xFF,0xFF,0x0C,0x00, /* 000006F8 "........" */ - 0x0A,0x02,0x4C,0x4E,0x4B,0x43,0x00,0x12, /* 00000700 "..LNKC.." */ - 0x0E,0x04,0x0C,0xFF,0xFF,0x0C,0x00,0x0A, /* 00000708 "........" */ - 0x03,0x4C,0x4E,0x4B,0x44,0x00,0x12,0x0D, /* 00000710 ".LNKD..." */ - 0x04,0x0C,0xFF,0xFF,0x0D,0x00,0x00,0x4C, /* 00000718 ".......L" */ - 0x4E,0x4B,0x42,0x00,0x12,0x0D,0x04,0x0C, /* 00000720 "NKB....." */ - 0xFF,0xFF,0x0D,0x00,0x01,0x4C,0x4E,0x4B, /* 00000728 ".....LNK" */ - 0x43,0x00,0x12,0x0E,0x04,0x0C,0xFF,0xFF, /* 00000730 "C......." */ - 0x0D,0x00,0x0A,0x02,0x4C,0x4E,0x4B,0x44, /* 00000738 "....LNKD" */ - 0x00,0x12,0x0E,0x04,0x0C,0xFF,0xFF,0x0D, /* 00000740 "........" */ - 0x00,0x0A,0x03,0x4C,0x4E,0x4B,0x41,0x00, /* 00000748 "...LNKA." */ - 0x12,0x0D,0x04,0x0C,0xFF,0xFF,0x0E,0x00, /* 00000750 "........" */ - 0x00,0x4C,0x4E,0x4B,0x43,0x00,0x12,0x0D, /* 00000758 ".LNKC..." */ - 0x04,0x0C,0xFF,0xFF,0x0E,0x00,0x01,0x4C, /* 00000760 ".......L" */ - 0x4E,0x4B,0x44,0x00,0x12,0x0E,0x04,0x0C, /* 00000768 "NKD....." */ - 0xFF,0xFF,0x0E,0x00,0x0A,0x02,0x4C,0x4E, /* 00000770 "......LN" */ - 0x4B,0x41,0x00,0x12,0x0E,0x04,0x0C,0xFF, /* 00000778 "KA......" */ - 0xFF,0x0E,0x00,0x0A,0x03,0x4C,0x4E,0x4B, /* 00000780 ".....LNK" */ - 0x42,0x00,0x12,0x0D,0x04,0x0C,0xFF,0xFF, /* 00000788 "B......." */ - 0x0F,0x00,0x00,0x4C,0x4E,0x4B,0x44,0x00, /* 00000790 "...LNKD." */ - 0x12,0x0D,0x04,0x0C,0xFF,0xFF,0x0F,0x00, /* 00000798 "........" */ - 0x01,0x4C,0x4E,0x4B,0x41,0x00,0x12,0x0E, /* 000007A0 ".LNKA..." */ - 0x04,0x0C,0xFF,0xFF,0x0F,0x00,0x0A,0x02, /* 000007A8 "........" */ - 0x4C,0x4E,0x4B,0x42,0x00,0x12,0x0E,0x04, /* 000007B0 "LNKB...." */ - 0x0C,0xFF,0xFF,0x0F,0x00,0x0A,0x03,0x4C, /* 000007B8 ".......L" */ - 0x4E,0x4B,0x43,0x00,0x08,0x50,0x52,0x54, /* 000007C0 "NKC..PRT" */ - 0x41,0x12,0x41,0x2F,0x3C,0x12,0x0B,0x04, /* 000007C8 "A.A/<..." */ - 0x0C,0xFF,0xFF,0x01,0x00,0x00,0x00,0x0A, /* 000007D0 "........" */ - 0x14,0x12,0x0B,0x04,0x0C,0xFF,0xFF,0x01, /* 000007D8 "........" */ - 0x00,0x01,0x00,0x0A,0x15,0x12,0x0C,0x04, /* 000007E0 "........" */ - 0x0C,0xFF,0xFF,0x01,0x00,0x0A,0x02,0x00, /* 000007E8 "........" */ - 0x0A,0x16,0x12,0x0C,0x04,0x0C,0xFF,0xFF, /* 000007F0 "........" */ - 0x01,0x00,0x0A,0x03,0x00,0x0A,0x17,0x12, /* 000007F8 "........" */ - 0x0B,0x04,0x0C,0xFF,0xFF,0x02,0x00,0x00, /* 00000800 "........" */ - 0x00,0x0A,0x18,0x12,0x0B,0x04,0x0C,0xFF, /* 00000808 "........" */ - 0xFF,0x02,0x00,0x01,0x00,0x0A,0x19,0x12, /* 00000810 "........" */ - 0x0C,0x04,0x0C,0xFF,0xFF,0x02,0x00,0x0A, /* 00000818 "........" */ - 0x02,0x00,0x0A,0x1A,0x12,0x0C,0x04,0x0C, /* 00000820 "........" */ - 0xFF,0xFF,0x02,0x00,0x0A,0x03,0x00,0x0A, /* 00000828 "........" */ - 0x1B,0x12,0x0B,0x04,0x0C,0xFF,0xFF,0x03, /* 00000830 "........" */ - 0x00,0x00,0x00,0x0A,0x1C,0x12,0x0B,0x04, /* 00000838 "........" */ - 0x0C,0xFF,0xFF,0x03,0x00,0x01,0x00,0x0A, /* 00000840 "........" */ - 0x1D,0x12,0x0C,0x04,0x0C,0xFF,0xFF,0x03, /* 00000848 "........" */ - 0x00,0x0A,0x02,0x00,0x0A,0x1E,0x12,0x0C, /* 00000850 "........" */ - 0x04,0x0C,0xFF,0xFF,0x03,0x00,0x0A,0x03, /* 00000858 "........" */ - 0x00,0x0A,0x1F,0x12,0x0B,0x04,0x0C,0xFF, /* 00000860 "........" */ - 0xFF,0x04,0x00,0x00,0x00,0x0A,0x20,0x12, /* 00000868 "...... ." */ - 0x0B,0x04,0x0C,0xFF,0xFF,0x04,0x00,0x01, /* 00000870 "........" */ - 0x00,0x0A,0x21,0x12,0x0C,0x04,0x0C,0xFF, /* 00000878 "..!....." */ - 0xFF,0x04,0x00,0x0A,0x02,0x00,0x0A,0x22, /* 00000880 "......."" */ - 0x12,0x0C,0x04,0x0C,0xFF,0xFF,0x04,0x00, /* 00000888 "........" */ - 0x0A,0x03,0x00,0x0A,0x23,0x12,0x0B,0x04, /* 00000890 "....#..." */ - 0x0C,0xFF,0xFF,0x05,0x00,0x00,0x00,0x0A, /* 00000898 "........" */ - 0x24,0x12,0x0B,0x04,0x0C,0xFF,0xFF,0x05, /* 000008A0 "$......." */ - 0x00,0x01,0x00,0x0A,0x25,0x12,0x0C,0x04, /* 000008A8 "....%..." */ - 0x0C,0xFF,0xFF,0x05,0x00,0x0A,0x02,0x00, /* 000008B0 "........" */ - 0x0A,0x26,0x12,0x0C,0x04,0x0C,0xFF,0xFF, /* 000008B8 ".&......" */ - 0x05,0x00,0x0A,0x03,0x00,0x0A,0x27,0x12, /* 000008C0 "......'." */ - 0x0B,0x04,0x0C,0xFF,0xFF,0x06,0x00,0x00, /* 000008C8 "........" */ - 0x00,0x0A,0x28,0x12,0x0B,0x04,0x0C,0xFF, /* 000008D0 "..(....." */ - 0xFF,0x06,0x00,0x01,0x00,0x0A,0x29,0x12, /* 000008D8 "......)." */ - 0x0C,0x04,0x0C,0xFF,0xFF,0x06,0x00,0x0A, /* 000008E0 "........" */ - 0x02,0x00,0x0A,0x2A,0x12,0x0C,0x04,0x0C, /* 000008E8 "...*...." */ - 0xFF,0xFF,0x06,0x00,0x0A,0x03,0x00,0x0A, /* 000008F0 "........" */ - 0x2B,0x12,0x0B,0x04,0x0C,0xFF,0xFF,0x07, /* 000008F8 "+......." */ - 0x00,0x00,0x00,0x0A,0x2C,0x12,0x0B,0x04, /* 00000900 "....,..." */ - 0x0C,0xFF,0xFF,0x07,0x00,0x01,0x00,0x0A, /* 00000908 "........" */ - 0x2D,0x12,0x0C,0x04,0x0C,0xFF,0xFF,0x07, /* 00000910 "-......." */ - 0x00,0x0A,0x02,0x00,0x0A,0x2E,0x12,0x0C, /* 00000918 "........" */ - 0x04,0x0C,0xFF,0xFF,0x07,0x00,0x0A,0x03, /* 00000920 "........" */ - 0x00,0x0A,0x2F,0x12,0x0B,0x04,0x0C,0xFF, /* 00000928 "../....." */ - 0xFF,0x08,0x00,0x00,0x00,0x0A,0x11,0x12, /* 00000930 "........" */ - 0x0B,0x04,0x0C,0xFF,0xFF,0x08,0x00,0x01, /* 00000938 "........" */ - 0x00,0x0A,0x12,0x12,0x0C,0x04,0x0C,0xFF, /* 00000940 "........" */ - 0xFF,0x08,0x00,0x0A,0x02,0x00,0x0A,0x13, /* 00000948 "........" */ - 0x12,0x0C,0x04,0x0C,0xFF,0xFF,0x08,0x00, /* 00000950 "........" */ - 0x0A,0x03,0x00,0x0A,0x14,0x12,0x0B,0x04, /* 00000958 "........" */ - 0x0C,0xFF,0xFF,0x09,0x00,0x00,0x00,0x0A, /* 00000960 "........" */ - 0x15,0x12,0x0B,0x04,0x0C,0xFF,0xFF,0x09, /* 00000968 "........" */ - 0x00,0x01,0x00,0x0A,0x16,0x12,0x0C,0x04, /* 00000970 "........" */ - 0x0C,0xFF,0xFF,0x09,0x00,0x0A,0x02,0x00, /* 00000978 "........" */ - 0x0A,0x17,0x12,0x0C,0x04,0x0C,0xFF,0xFF, /* 00000980 "........" */ - 0x09,0x00,0x0A,0x03,0x00,0x0A,0x18,0x12, /* 00000988 "........" */ - 0x0B,0x04,0x0C,0xFF,0xFF,0x0A,0x00,0x00, /* 00000990 "........" */ - 0x00,0x0A,0x19,0x12,0x0B,0x04,0x0C,0xFF, /* 00000998 "........" */ - 0xFF,0x0A,0x00,0x01,0x00,0x0A,0x1A,0x12, /* 000009A0 "........" */ - 0x0C,0x04,0x0C,0xFF,0xFF,0x0A,0x00,0x0A, /* 000009A8 "........" */ - 0x02,0x00,0x0A,0x1B,0x12,0x0C,0x04,0x0C, /* 000009B0 "........" */ - 0xFF,0xFF,0x0A,0x00,0x0A,0x03,0x00,0x0A, /* 000009B8 "........" */ - 0x1C,0x12,0x0B,0x04,0x0C,0xFF,0xFF,0x0B, /* 000009C0 "........" */ - 0x00,0x00,0x00,0x0A,0x1D,0x12,0x0B,0x04, /* 000009C8 "........" */ - 0x0C,0xFF,0xFF,0x0B,0x00,0x01,0x00,0x0A, /* 000009D0 "........" */ - 0x1E,0x12,0x0C,0x04,0x0C,0xFF,0xFF,0x0B, /* 000009D8 "........" */ - 0x00,0x0A,0x02,0x00,0x0A,0x1F,0x12,0x0C, /* 000009E0 "........" */ - 0x04,0x0C,0xFF,0xFF,0x0B,0x00,0x0A,0x03, /* 000009E8 "........" */ - 0x00,0x0A,0x20,0x12,0x0B,0x04,0x0C,0xFF, /* 000009F0 ".. ....." */ - 0xFF,0x0C,0x00,0x00,0x00,0x0A,0x21,0x12, /* 000009F8 "......!." */ - 0x0B,0x04,0x0C,0xFF,0xFF,0x0C,0x00,0x01, /* 00000A00 "........" */ - 0x00,0x0A,0x22,0x12,0x0C,0x04,0x0C,0xFF, /* 00000A08 ".."....." */ - 0xFF,0x0C,0x00,0x0A,0x02,0x00,0x0A,0x23, /* 00000A10 ".......#" */ - 0x12,0x0C,0x04,0x0C,0xFF,0xFF,0x0C,0x00, /* 00000A18 "........" */ - 0x0A,0x03,0x00,0x0A,0x24,0x12,0x0B,0x04, /* 00000A20 "....$..." */ - 0x0C,0xFF,0xFF,0x0D,0x00,0x00,0x00,0x0A, /* 00000A28 "........" */ - 0x25,0x12,0x0B,0x04,0x0C,0xFF,0xFF,0x0D, /* 00000A30 "%......." */ - 0x00,0x01,0x00,0x0A,0x26,0x12,0x0C,0x04, /* 00000A38 "....&..." */ - 0x0C,0xFF,0xFF,0x0D,0x00,0x0A,0x02,0x00, /* 00000A40 "........" */ - 0x0A,0x27,0x12,0x0C,0x04,0x0C,0xFF,0xFF, /* 00000A48 ".'......" */ - 0x0D,0x00,0x0A,0x03,0x00,0x0A,0x28,0x12, /* 00000A50 "......(." */ - 0x0B,0x04,0x0C,0xFF,0xFF,0x0E,0x00,0x00, /* 00000A58 "........" */ - 0x00,0x0A,0x29,0x12,0x0B,0x04,0x0C,0xFF, /* 00000A60 "..)....." */ - 0xFF,0x0E,0x00,0x01,0x00,0x0A,0x2A,0x12, /* 00000A68 "......*." */ - 0x0C,0x04,0x0C,0xFF,0xFF,0x0E,0x00,0x0A, /* 00000A70 "........" */ - 0x02,0x00,0x0A,0x2B,0x12,0x0C,0x04,0x0C, /* 00000A78 "...+...." */ - 0xFF,0xFF,0x0E,0x00,0x0A,0x03,0x00,0x0A, /* 00000A80 "........" */ - 0x2C,0x12,0x0B,0x04,0x0C,0xFF,0xFF,0x0F, /* 00000A88 ",......." */ - 0x00,0x00,0x00,0x0A,0x2D,0x12,0x0B,0x04, /* 00000A90 "....-..." */ - 0x0C,0xFF,0xFF,0x0F,0x00,0x01,0x00,0x0A, /* 00000A98 "........" */ - 0x2E,0x12,0x0C,0x04,0x0C,0xFF,0xFF,0x0F, /* 00000AA0 "........" */ - 0x00,0x0A,0x02,0x00,0x0A,0x2F,0x12,0x0C, /* 00000AA8 "...../.." */ - 0x04,0x0C,0xFF,0xFF,0x0F,0x00,0x0A,0x03, /* 00000AB0 "........" */ - 0x00,0x0A,0x10,0x5B,0x82,0x4C,0x31,0x49, /* 00000AB8 "...[.L1I" */ - 0x53,0x41,0x5F,0x08,0x5F,0x41,0x44,0x52, /* 00000AC0 "SA_._ADR" */ - 0x0C,0x00,0x00,0x01,0x00,0x5B,0x80,0x50, /* 00000AC8 ".....[.P" */ - 0x49,0x52,0x51,0x02,0x0A,0x60,0x0A,0x04, /* 00000AD0 "IRQ..`.." */ - 0x10,0x2E,0x5C,0x00,0x5B,0x81,0x29,0x5C, /* 00000AD8 "..\.[.)\" */ - 0x2F,0x04,0x5F,0x53,0x42,0x5F,0x50,0x43, /* 00000AE0 "/._SB_PC" */ - 0x49,0x30,0x49,0x53,0x41,0x5F,0x50,0x49, /* 00000AE8 "I0ISA_PI" */ - 0x52,0x51,0x01,0x50,0x49,0x52,0x41,0x08, /* 00000AF0 "RQ.PIRA." */ - 0x50,0x49,0x52,0x42,0x08,0x50,0x49,0x52, /* 00000AF8 "PIRB.PIR" */ - 0x43,0x08,0x50,0x49,0x52,0x44,0x08,0x5B, /* 00000B00 "C.PIRD.[" */ - 0x82,0x46,0x0B,0x53,0x59,0x53,0x52,0x08, /* 00000B08 ".F.SYSR." */ - 0x5F,0x48,0x49,0x44,0x0C,0x41,0xD0,0x0C, /* 00000B10 "_HID.A.." */ - 0x02,0x08,0x5F,0x55,0x49,0x44,0x01,0x08, /* 00000B18 ".._UID.." */ - 0x43,0x52,0x53,0x5F,0x11,0x4E,0x08,0x0A, /* 00000B20 "CRS_.N.." */ - 0x8A,0x47,0x01,0x10,0x00,0x10,0x00,0x00, /* 00000B28 ".G......" */ - 0x10,0x47,0x01,0x22,0x00,0x22,0x00,0x00, /* 00000B30 ".G.".".." */ - 0x0C,0x47,0x01,0x30,0x00,0x30,0x00,0x00, /* 00000B38 ".G.0.0.." */ - 0x10,0x47,0x01,0x44,0x00,0x44,0x00,0x00, /* 00000B40 ".G.D.D.." */ - 0x1C,0x47,0x01,0x62,0x00,0x62,0x00,0x00, /* 00000B48 ".G.b.b.." */ - 0x02,0x47,0x01,0x65,0x00,0x65,0x00,0x00, /* 00000B50 ".G.e.e.." */ - 0x0B,0x47,0x01,0x72,0x00,0x72,0x00,0x00, /* 00000B58 ".G.r.r.." */ - 0x0E,0x47,0x01,0x80,0x00,0x80,0x00,0x00, /* 00000B60 ".G......" */ - 0x01,0x47,0x01,0x84,0x00,0x84,0x00,0x00, /* 00000B68 ".G......" */ - 0x03,0x47,0x01,0x88,0x00,0x88,0x00,0x00, /* 00000B70 ".G......" */ - 0x01,0x47,0x01,0x8C,0x00,0x8C,0x00,0x00, /* 00000B78 ".G......" */ - 0x03,0x47,0x01,0x90,0x00,0x90,0x00,0x00, /* 00000B80 ".G......" */ - 0x10,0x47,0x01,0xA2,0x00,0xA2,0x00,0x00, /* 00000B88 ".G......" */ - 0x1C,0x47,0x01,0xE0,0x00,0xE0,0x00,0x00, /* 00000B90 ".G......" */ - 0x10,0x47,0x01,0xA0,0x08,0xA0,0x08,0x00, /* 00000B98 ".G......" */ - 0x04,0x47,0x01,0xC0,0x0C,0xC0,0x0C,0x00, /* 00000BA0 ".G......" */ - 0x10,0x47,0x01,0xD0,0x04,0xD0,0x04,0x00, /* 00000BA8 ".G......" */ - 0x02,0x79,0x00,0x14,0x0B,0x5F,0x43,0x52, /* 00000BB0 ".y..._CR" */ - 0x53,0x00,0xA4,0x43,0x52,0x53,0x5F,0x5B, /* 00000BB8 "S..CRS_[" */ - 0x82,0x2B,0x50,0x49,0x43,0x5F,0x08,0x5F, /* 00000BC0 ".+PIC_._" */ - 0x48,0x49,0x44,0x0B,0x41,0xD0,0x08,0x5F, /* 00000BC8 "HID.A.._" */ - 0x43,0x52,0x53,0x11,0x18,0x0A,0x15,0x47, /* 00000BD0 "CRS....G" */ - 0x01,0x20,0x00,0x20,0x00,0x01,0x02,0x47, /* 00000BD8 ". . ...G" */ - 0x01,0xA0,0x00,0xA0,0x00,0x01,0x02,0x22, /* 00000BE0 "......."" */ - 0x04,0x00,0x79,0x00,0x5B,0x82,0x47,0x05, /* 00000BE8 "..y.[.G." */ - 0x44,0x4D,0x41,0x30,0x08,0x5F,0x48,0x49, /* 00000BF0 "DMA0._HI" */ - 0x44,0x0C,0x41,0xD0,0x02,0x00,0x08,0x5F, /* 00000BF8 "D.A...._" */ - 0x43,0x52,0x53,0x11,0x41,0x04,0x0A,0x3D, /* 00000C00 "CRS.A..=" */ - 0x2A,0x10,0x04,0x47,0x01,0x00,0x00,0x00, /* 00000C08 "*..G...." */ - 0x00,0x00,0x10,0x47,0x01,0x81,0x00,0x81, /* 00000C10 "...G...." */ - 0x00,0x00,0x03,0x47,0x01,0x87,0x00,0x87, /* 00000C18 "...G...." */ - 0x00,0x00,0x01,0x47,0x01,0x89,0x00,0x89, /* 00000C20 "...G...." */ - 0x00,0x00,0x03,0x47,0x01,0x8F,0x00,0x8F, /* 00000C28 "...G...." */ - 0x00,0x00,0x01,0x47,0x01,0xC0,0x00,0xC0, /* 00000C30 "...G...." */ - 0x00,0x00,0x20,0x47,0x01,0x80,0x04,0x80, /* 00000C38 ".. G...." */ - 0x04,0x00,0x10,0x79,0x00,0x5B,0x82,0x25, /* 00000C40 "...y.[.%" */ - 0x54,0x4D,0x52,0x5F,0x08,0x5F,0x48,0x49, /* 00000C48 "TMR_._HI" */ - 0x44,0x0C,0x41,0xD0,0x01,0x00,0x08,0x5F, /* 00000C50 "D.A...._" */ - 0x43,0x52,0x53,0x11,0x10,0x0A,0x0D,0x47, /* 00000C58 "CRS....G" */ - 0x01,0x40,0x00,0x40,0x00,0x00,0x04,0x22, /* 00000C60 ".@.@..."" */ - 0x01,0x00,0x79,0x00,0x5B,0x82,0x25,0x52, /* 00000C68 "..y.[.%R" */ - 0x54,0x43,0x5F,0x08,0x5F,0x48,0x49,0x44, /* 00000C70 "TC_._HID" */ - 0x0C,0x41,0xD0,0x0B,0x00,0x08,0x5F,0x43, /* 00000C78 ".A...._C" */ - 0x52,0x53,0x11,0x10,0x0A,0x0D,0x47,0x01, /* 00000C80 "RS....G." */ - 0x70,0x00,0x70,0x00,0x00,0x02,0x22,0x00, /* 00000C88 "p.p..."." */ - 0x01,0x79,0x00,0x5B,0x82,0x22,0x53,0x50, /* 00000C90 ".y.[."SP" */ - 0x4B,0x52,0x08,0x5F,0x48,0x49,0x44,0x0C, /* 00000C98 "KR._HID." */ - 0x41,0xD0,0x08,0x00,0x08,0x5F,0x43,0x52, /* 00000CA0 "A...._CR" */ - 0x53,0x11,0x0D,0x0A,0x0A,0x47,0x01,0x61, /* 00000CA8 "S....G.a" */ - 0x00,0x61,0x00,0x00,0x01,0x79,0x00,0x5B, /* 00000CB0 ".a...y.[" */ - 0x82,0x31,0x50,0x53,0x32,0x4D,0x08,0x5F, /* 00000CB8 ".1PS2M._" */ - 0x48,0x49,0x44,0x0C,0x41,0xD0,0x0F,0x13, /* 00000CC0 "HID.A..." */ - 0x08,0x5F,0x43,0x49,0x44,0x0C,0x41,0xD0, /* 00000CC8 "._CID.A." */ - 0x0F,0x13,0x14,0x09,0x5F,0x53,0x54,0x41, /* 00000CD0 "...._STA" */ - 0x00,0xA4,0x0A,0x0F,0x08,0x5F,0x43,0x52, /* 00000CD8 "....._CR" */ - 0x53,0x11,0x08,0x0A,0x05,0x22,0x00,0x10, /* 00000CE0 "S....".." */ - 0x79,0x00,0x5B,0x82,0x42,0x04,0x50,0x53, /* 00000CE8 "y.[.B.PS" */ - 0x32,0x4B,0x08,0x5F,0x48,0x49,0x44,0x0C, /* 00000CF0 "2K._HID." */ - 0x41,0xD0,0x03,0x03,0x08,0x5F,0x43,0x49, /* 00000CF8 "A...._CI" */ - 0x44,0x0C,0x41,0xD0,0x03,0x0B,0x14,0x09, /* 00000D00 "D.A....." */ - 0x5F,0x53,0x54,0x41,0x00,0xA4,0x0A,0x0F, /* 00000D08 "_STA...." */ - 0x08,0x5F,0x43,0x52,0x53,0x11,0x18,0x0A, /* 00000D10 "._CRS..." */ - 0x15,0x47,0x01,0x60,0x00,0x60,0x00,0x00, /* 00000D18 ".G.`.`.." */ - 0x01,0x47,0x01,0x64,0x00,0x64,0x00,0x00, /* 00000D20 ".G.d.d.." */ - 0x01,0x22,0x02,0x00,0x79,0x00,0x5B,0x82, /* 00000D28 "."..y.[." */ - 0x3A,0x46,0x44,0x43,0x30,0x08,0x5F,0x48, /* 00000D30 ":FDC0._H" */ - 0x49,0x44,0x0C,0x41,0xD0,0x07,0x00,0x14, /* 00000D38 "ID.A...." */ - 0x09,0x5F,0x53,0x54,0x41,0x00,0xA4,0x0A, /* 00000D40 "._STA..." */ - 0x0F,0x08,0x5F,0x43,0x52,0x53,0x11,0x1B, /* 00000D48 ".._CRS.." */ - 0x0A,0x18,0x47,0x01,0xF0,0x03,0xF0,0x03, /* 00000D50 "..G....." */ - 0x01,0x06,0x47,0x01,0xF7,0x03,0xF7,0x03, /* 00000D58 "..G....." */ - 0x01,0x01,0x22,0x40,0x00,0x2A,0x04,0x00, /* 00000D60 ".."@.*.." */ - 0x79,0x00,0x5B,0x82,0x35,0x55,0x41,0x52, /* 00000D68 "y.[.5UAR" */ - 0x31,0x08,0x5F,0x48,0x49,0x44,0x0C,0x41, /* 00000D70 "1._HID.A" */ - 0xD0,0x05,0x01,0x08,0x5F,0x55,0x49,0x44, /* 00000D78 "...._UID" */ - 0x01,0x14,0x09,0x5F,0x53,0x54,0x41,0x00, /* 00000D80 "..._STA." */ - 0xA4,0x0A,0x0F,0x08,0x5F,0x43,0x52,0x53, /* 00000D88 "...._CRS" */ - 0x11,0x10,0x0A,0x0D,0x47,0x01,0xF8,0x03, /* 00000D90 "....G..." */ - 0xF8,0x03,0x01,0x08,0x22,0x10,0x00,0x79, /* 00000D98 "...."..y" */ - 0x00,0x5B,0x82,0x36,0x4C,0x54,0x50,0x31, /* 00000DA0 ".[.6LTP1" */ - 0x08,0x5F,0x48,0x49,0x44,0x0C,0x41,0xD0, /* 00000DA8 "._HID.A." */ - 0x04,0x00,0x08,0x5F,0x55,0x49,0x44,0x0A, /* 00000DB0 "..._UID." */ - 0x02,0x14,0x09,0x5F,0x53,0x54,0x41,0x00, /* 00000DB8 "..._STA." */ - 0xA4,0x0A,0x0F,0x08,0x5F,0x43,0x52,0x53, /* 00000DC0 "...._CRS" */ - 0x11,0x10,0x0A,0x0D,0x47,0x01,0x78,0x03, /* 00000DC8 "....G.x." */ - 0x78,0x03,0x08,0x08,0x22,0x80,0x00,0x79, /* 00000DD0 "x..."..y" */ - 0x00, + 0x00,0x08,0x5F,0x53,0x35,0x5F,0x12,0x08, /* 00000058 ".._S5_.." */ + 0x04,0x0A,0x07,0x0A,0x07,0x00,0x00,0x08, /* 00000060 "........" */ + 0x50,0x49,0x43,0x44,0x00,0x14,0x0C,0x5F, /* 00000068 "PICD..._" */ + 0x50,0x49,0x43,0x01,0x70,0x68,0x50,0x49, /* 00000070 "PIC.phPI" */ + 0x43,0x44,0x10,0x44,0xD2,0x5F,0x53,0x42, /* 00000078 "CD.D._SB" */ + 0x5F,0x5B,0x82,0x49,0x04,0x4D,0x45,0x4D, /* 00000080 "_[.I.MEM" */ + 0x30,0x08,0x5F,0x48,0x49,0x44,0x0C,0x41, /* 00000088 "0._HID.A" */ + 0xD0,0x0C,0x02,0x08,0x5F,0x43,0x52,0x53, /* 00000090 "...._CRS" */ + 0x11,0x33,0x0A,0x30,0x8A,0x2B,0x00,0x00, /* 00000098 ".3.0.+.." */ + 0x0D,0x03,0x00,0x00,0x00,0x00,0x00,0x00, /* 000000A0 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 000000A8 "........" */ + 0x00,0x00,0xFF,0xFF,0x09,0x00,0x00,0x00, /* 000000B0 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 000000B8 "........" */ + 0x00,0x00,0x00,0x00,0x0A,0x00,0x00,0x00, /* 000000C0 "........" */ + 0x00,0x00,0x79,0x00,0x5B,0x82,0x41,0xCD, /* 000000C8 "..y.[.A." */ + 0x50,0x43,0x49,0x30,0x08,0x5F,0x48,0x49, /* 000000D0 "PCI0._HI" */ + 0x44,0x0C,0x41,0xD0,0x0A,0x03,0x08,0x5F, /* 000000D8 "D.A...._" */ + 0x55,0x49,0x44,0x00,0x08,0x5F,0x41,0x44, /* 000000E0 "UID.._AD" */ + 0x52,0x00,0x08,0x5F,0x42,0x42,0x4E,0x00, /* 000000E8 "R.._BBN." */ + 0x14,0x44,0x08,0x5F,0x43,0x52,0x53,0x00, /* 000000F0 ".D._CRS." */ + 0x08,0x50,0x52,0x54,0x30,0x11,0x42,0x07, /* 000000F8 ".PRT0.B." */ + 0x0A,0x6E,0x88,0x0D,0x00,0x02,0x0F,0x00, /* 00000100 ".n......" */ + 0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00, /* 00000108 "........" */ + 0x00,0x01,0x47,0x01,0xF8,0x0C,0xF8,0x0C, /* 00000110 "..G....." */ + 0x01,0x08,0x88,0x0D,0x00,0x01,0x0C,0x03, /* 00000118 "........" */ + 0x00,0x00,0x00,0x00,0xF7,0x0C,0x00,0x00, /* 00000120 "........" */ + 0xF8,0x0C,0x88,0x0D,0x00,0x01,0x0C,0x03, /* 00000128 "........" */ + 0x00,0x00,0x00,0x0D,0xFF,0xFF,0x00,0x00, /* 00000130 "........" */ + 0x00,0xF3,0x87,0x17,0x00,0x00,0x0C,0x03, /* 00000138 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x0A,0x00, /* 00000140 "........" */ + 0xFF,0xFF,0x0B,0x00,0x00,0x00,0x00,0x00, /* 00000148 "........" */ + 0x00,0x00,0x02,0x00,0x87,0x17,0x00,0x00, /* 00000150 "........" */ + 0x0D,0x03,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000158 "........" */ + 0x00,0xF0,0xFF,0xFF,0xFF,0xF4,0x00,0x00, /* 00000160 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x05,0x79,0x00, /* 00000168 "......y." */ + 0xA4,0x50,0x52,0x54,0x30,0x08,0x42,0x55, /* 00000170 ".PRT0.BU" */ + 0x46,0x41,0x11,0x09,0x0A,0x06,0x23,0x60, /* 00000178 "FA....#`" */ + 0x0C,0x18,0x79,0x00,0x08,0x42,0x55,0x46, /* 00000180 "..y..BUF" */ + 0x42,0x11,0x09,0x0A,0x06,0x23,0x00,0x00, /* 00000188 "B....#.." */ + 0x18,0x79,0x00,0x8B,0x42,0x55,0x46,0x42, /* 00000190 ".y..BUFB" */ + 0x01,0x49,0x52,0x51,0x56,0x5B,0x82,0x48, /* 00000198 ".IRQV[.H" */ + 0x08,0x4C,0x4E,0x4B,0x41,0x08,0x5F,0x48, /* 000001A0 ".LNKA._H" */ + 0x49,0x44,0x0C,0x41,0xD0,0x0C,0x0F,0x08, /* 000001A8 "ID.A...." */ + 0x5F,0x55,0x49,0x44,0x01,0x14,0x1C,0x5F, /* 000001B0 "_UID..._" */ + 0x53,0x54,0x41,0x00,0x7B,0x50,0x49,0x52, /* 000001B8 "STA.{PIR" */ + 0x41,0x0A,0x80,0x60,0xA0,0x08,0x93,0x60, /* 000001C0 "A..`...`" */ + 0x0A,0x80,0xA4,0x0A,0x09,0xA1,0x04,0xA4, /* 000001C8 "........" */ + 0x0A,0x0B,0x14,0x0B,0x5F,0x50,0x52,0x53, /* 000001D0 "...._PRS" */ + 0x00,0xA4,0x42,0x55,0x46,0x41,0x14,0x11, /* 000001D8 "..BUFA.." */ + 0x5F,0x44,0x49,0x53,0x00,0x7D,0x50,0x49, /* 000001E0 "_DIS.}PI" */ + 0x52,0x41,0x0A,0x80,0x50,0x49,0x52,0x41, /* 000001E8 "RA..PIRA" */ + 0x14,0x1A,0x5F,0x43,0x52,0x53,0x00,0x7B, /* 000001F0 ".._CRS.{" */ + 0x50,0x49,0x52,0x41,0x0A,0x0F,0x60,0x79, /* 000001F8 "PIRA..`y" */ + 0x01,0x60,0x49,0x52,0x51,0x56,0xA4,0x42, /* 00000200 ".`IRQV.B" */ + 0x55,0x46,0x42,0x14,0x1B,0x5F,0x53,0x52, /* 00000208 "UFB.._SR" */ + 0x53,0x01,0x8B,0x68,0x01,0x49,0x52,0x51, /* 00000210 "S..h.IRQ" */ + 0x31,0x82,0x49,0x52,0x51,0x31,0x60,0x76, /* 00000218 "1.IRQ1`v" */ + 0x60,0x70,0x60,0x50,0x49,0x52,0x41,0x5B, /* 00000220 "`p`PIRA[" */ + 0x82,0x49,0x08,0x4C,0x4E,0x4B,0x42,0x08, /* 00000228 ".I.LNKB." */ + 0x5F,0x48,0x49,0x44,0x0C,0x41,0xD0,0x0C, /* 00000230 "_HID.A.." */ + 0x0F,0x08,0x5F,0x55,0x49,0x44,0x0A,0x02, /* 00000238 ".._UID.." */ + 0x14,0x1C,0x5F,0x53,0x54,0x41,0x00,0x7B, /* 00000240 ".._STA.{" */ + 0x50,0x49,0x52,0x42,0x0A,0x80,0x60,0xA0, /* 00000248 "PIRB..`." */ + 0x08,0x93,0x60,0x0A,0x80,0xA4,0x0A,0x09, /* 00000250 "..`....." */ + 0xA1,0x04,0xA4,0x0A,0x0B,0x14,0x0B,0x5F, /* 00000258 "......._" */ + 0x50,0x52,0x53,0x00,0xA4,0x42,0x55,0x46, /* 00000260 "PRS..BUF" */ + 0x41,0x14,0x11,0x5F,0x44,0x49,0x53,0x00, /* 00000268 "A.._DIS." */ + 0x7D,0x50,0x49,0x52,0x42,0x0A,0x80,0x50, /* 00000270 "}PIRB..P" */ + 0x49,0x52,0x42,0x14,0x1A,0x5F,0x43,0x52, /* 00000278 "IRB.._CR" */ + 0x53,0x00,0x7B,0x50,0x49,0x52,0x42,0x0A, /* 00000280 "S.{PIRB." */ + 0x0F,0x60,0x79,0x01,0x60,0x49,0x52,0x51, /* 00000288 ".`y.`IRQ" */ + 0x56,0xA4,0x42,0x55,0x46,0x42,0x14,0x1B, /* 00000290 "V.BUFB.." */ + 0x5F,0x53,0x52,0x53,0x01,0x8B,0x68,0x01, /* 00000298 "_SRS..h." */ + 0x49,0x52,0x51,0x31,0x82,0x49,0x52,0x51, /* 000002A0 "IRQ1.IRQ" */ + 0x31,0x60,0x76,0x60,0x70,0x60,0x50,0x49, /* 000002A8 "1`v`p`PI" */ + 0x52,0x42,0x5B,0x82,0x49,0x08,0x4C,0x4E, /* 000002B0 "RB[.I.LN" */ + 0x4B,0x43,0x08,0x5F,0x48,0x49,0x44,0x0C, /* 000002B8 "KC._HID." */ + 0x41,0xD0,0x0C,0x0F,0x08,0x5F,0x55,0x49, /* 000002C0 "A...._UI" */ + 0x44,0x0A,0x03,0x14,0x1C,0x5F,0x53,0x54, /* 000002C8 "D...._ST" */ + 0x41,0x00,0x7B,0x50,0x49,0x52,0x43,0x0A, /* 000002D0 "A.{PIRC." */ + 0x80,0x60,0xA0,0x08,0x93,0x60,0x0A,0x80, /* 000002D8 ".`...`.." */ + 0xA4,0x0A,0x09,0xA1,0x04,0xA4,0x0A,0x0B, /* 000002E0 "........" */ + 0x14,0x0B,0x5F,0x50,0x52,0x53,0x00,0xA4, /* 000002E8 ".._PRS.." */ + 0x42,0x55,0x46,0x41,0x14,0x11,0x5F,0x44, /* 000002F0 "BUFA.._D" */ + 0x49,0x53,0x00,0x7D,0x50,0x49,0x52,0x43, /* 000002F8 "IS.}PIRC" */ + 0x0A,0x80,0x50,0x49,0x52,0x43,0x14,0x1A, /* 00000300 "..PIRC.." */ + 0x5F,0x43,0x52,0x53,0x00,0x7B,0x50,0x49, /* 00000308 "_CRS.{PI" */ + 0x52,0x43,0x0A,0x0F,0x60,0x79,0x01,0x60, /* 00000310 "RC..`y.`" */ + 0x49,0x52,0x51,0x56,0xA4,0x42,0x55,0x46, /* 00000318 "IRQV.BUF" */ + 0x42,0x14,0x1B,0x5F,0x53,0x52,0x53,0x01, /* 00000320 "B.._SRS." */ + 0x8B,0x68,0x01,0x49,0x52,0x51,0x31,0x82, /* 00000328 ".h.IRQ1." */ + 0x49,0x52,0x51,0x31,0x60,0x76,0x60,0x70, /* 00000330 "IRQ1`v`p" */ + 0x60,0x50,0x49,0x52,0x43,0x5B,0x82,0x49, /* 00000338 "`PIRC[.I" */ + 0x08,0x4C,0x4E,0x4B,0x44,0x08,0x5F,0x48, /* 00000340 ".LNKD._H" */ + 0x49,0x44,0x0C,0x41,0xD0,0x0C,0x0F,0x08, /* 00000348 "ID.A...." */ + 0x5F,0x55,0x49,0x44,0x0A,0x04,0x14,0x1C, /* 00000350 "_UID...." */ + 0x5F,0x53,0x54,0x41,0x00,0x7B,0x50,0x49, /* 00000358 "_STA.{PI" */ + 0x52,0x44,0x0A,0x80,0x60,0xA0,0x08,0x93, /* 00000360 "RD..`..." */ + 0x60,0x0A,0x80,0xA4,0x0A,0x09,0xA1,0x04, /* 00000368 "`......." */ + 0xA4,0x0A,0x0B,0x14,0x0B,0x5F,0x50,0x52, /* 00000370 "....._PR" */ + 0x53,0x00,0xA4,0x42,0x55,0x46,0x41,0x14, /* 00000378 "S..BUFA." */ + 0x11,0x5F,0x44,0x49,0x53,0x00,0x7D,0x50, /* 00000380 "._DIS.}P" */ + 0x49,0x52,0x44,0x0A,0x80,0x50,0x49,0x52, /* 00000388 "IRD..PIR" */ + 0x44,0x14,0x1A,0x5F,0x43,0x52,0x53,0x00, /* 00000390 "D.._CRS." */ + 0x7B,0x50,0x49,0x52,0x44,0x0A,0x0F,0x60, /* 00000398 "{PIRD..`" */ + 0x79,0x01,0x60,0x49,0x52,0x51,0x56,0xA4, /* 000003A0 "y.`IRQV." */ + 0x42,0x55,0x46,0x42,0x14,0x1B,0x5F,0x53, /* 000003A8 "BUFB.._S" */ + 0x52,0x53,0x01,0x8B,0x68,0x01,0x49,0x52, /* 000003B0 "RS..h.IR" */ + 0x51,0x31,0x82,0x49,0x52,0x51,0x31,0x60, /* 000003B8 "Q1.IRQ1`" */ + 0x76,0x60,0x70,0x60,0x50,0x49,0x52,0x44, /* 000003C0 "v`p`PIRD" */ + 0x5B,0x82,0x3A,0x48,0x50,0x45,0x54,0x08, /* 000003C8 "[.:HPET." */ + 0x5F,0x48,0x49,0x44,0x0C,0x41,0xD0,0x01, /* 000003D0 "_HID.A.." */ + 0x03,0x08,0x5F,0x55,0x49,0x44,0x00,0x08, /* 000003D8 ".._UID.." */ + 0x5F,0x43,0x52,0x53,0x11,0x1F,0x0A,0x1C, /* 000003E0 "_CRS...." */ + 0x87,0x17,0x00,0x00,0x0D,0x01,0x00,0x00, /* 000003E8 "........" */ + 0x00,0x00,0x00,0x00,0xD0,0xFE,0xFF,0x03, /* 000003F0 "........" */ + 0xD0,0xFE,0x00,0x00,0x00,0x00,0x00,0x04, /* 000003F8 "........" */ + 0x00,0x00,0x79,0x00,0x14,0x16,0x5F,0x50, /* 00000400 "..y..._P" */ + 0x52,0x54,0x00,0xA0,0x0A,0x50,0x49,0x43, /* 00000408 "RT...PIC" */ + 0x44,0xA4,0x50,0x52,0x54,0x41,0xA4,0x50, /* 00000410 "D.PRTA.P" */ + 0x52,0x54,0x50,0x08,0x50,0x52,0x54,0x50, /* 00000418 "RTP.PRTP" */ + 0x12,0x49,0x36,0x3C,0x12,0x0D,0x04,0x0C, /* 00000420 ".I6<...." */ + 0xFF,0xFF,0x01,0x00,0x00,0x4C,0x4E,0x4B, /* 00000428 ".....LNK" */ + 0x42,0x00,0x12,0x0D,0x04,0x0C,0xFF,0xFF, /* 00000430 "B......." */ + 0x01,0x00,0x01,0x4C,0x4E,0x4B,0x43,0x00, /* 00000438 "...LNKC." */ + 0x12,0x0E,0x04,0x0C,0xFF,0xFF,0x01,0x00, /* 00000440 "........" */ + 0x0A,0x02,0x4C,0x4E,0x4B,0x44,0x00,0x12, /* 00000448 "..LNKD.." */ + 0x0E,0x04,0x0C,0xFF,0xFF,0x01,0x00,0x0A, /* 00000450 "........" */ + 0x03,0x4C,0x4E,0x4B,0x41,0x00,0x12,0x0D, /* 00000458 ".LNKA..." */ + 0x04,0x0C,0xFF,0xFF,0x02,0x00,0x00,0x4C, /* 00000460 ".......L" */ + 0x4E,0x4B,0x43,0x00,0x12,0x0D,0x04,0x0C, /* 00000468 "NKC....." */ + 0xFF,0xFF,0x02,0x00,0x01,0x4C,0x4E,0x4B, /* 00000470 ".....LNK" */ + 0x44,0x00,0x12,0x0E,0x04,0x0C,0xFF,0xFF, /* 00000478 "D......." */ + 0x02,0x00,0x0A,0x02,0x4C,0x4E,0x4B,0x41, /* 00000480 "....LNKA" */ + 0x00,0x12,0x0E,0x04,0x0C,0xFF,0xFF,0x02, /* 00000488 "........" */ + 0x00,0x0A,0x03,0x4C,0x4E,0x4B,0x42,0x00, /* 00000490 "...LNKB." */ + 0x12,0x0D,0x04,0x0C,0xFF,0xFF,0x03,0x00, /* 00000498 "........" */ + 0x00,0x4C,0x4E,0x4B,0x44,0x00,0x12,0x0D, /* 000004A0 ".LNKD..." */ + 0x04,0x0C,0xFF,0xFF,0x03,0x00,0x01,0x4C, /* 000004A8 ".......L" */ + 0x4E,0x4B,0x41,0x00,0x12,0x0E,0x04,0x0C, /* 000004B0 "NKA....." */ + 0xFF,0xFF,0x03,0x00,0x0A,0x02,0x4C,0x4E, /* 000004B8 "......LN" */ + 0x4B,0x42,0x00,0x12,0x0E,0x04,0x0C,0xFF, /* 000004C0 "KB......" */ + 0xFF,0x03,0x00,0x0A,0x03,0x4C,0x4E,0x4B, /* 000004C8 ".....LNK" */ + 0x43,0x00,0x12,0x0D,0x04,0x0C,0xFF,0xFF, /* 000004D0 "C......." */ + 0x04,0x00,0x00,0x4C,0x4E,0x4B,0x41,0x00, /* 000004D8 "...LNKA." */ + 0x12,0x0D,0x04,0x0C,0xFF,0xFF,0x04,0x00, /* 000004E0 "........" */ + 0x01,0x4C,0x4E,0x4B,0x42,0x00,0x12,0x0E, /* 000004E8 ".LNKB..." */ + 0x04,0x0C,0xFF,0xFF,0x04,0x00,0x0A,0x02, /* 000004F0 "........" */ + 0x4C,0x4E,0x4B,0x43,0x00,0x12,0x0E,0x04, /* 000004F8 "LNKC...." */ + 0x0C,0xFF,0xFF,0x04,0x00,0x0A,0x03,0x4C, /* 00000500 ".......L" */ + 0x4E,0x4B,0x44,0x00,0x12,0x0D,0x04,0x0C, /* 00000508 "NKD....." */ + 0xFF,0xFF,0x05,0x00,0x00,0x4C,0x4E,0x4B, /* 00000510 ".....LNK" */ + 0x42,0x00,0x12,0x0D,0x04,0x0C,0xFF,0xFF, /* 00000518 "B......." */ + 0x05,0x00,0x01,0x4C,0x4E,0x4B,0x43,0x00, /* 00000520 "...LNKC." */ + 0x12,0x0E,0x04,0x0C,0xFF,0xFF,0x05,0x00, /* 00000528 "........" */ + 0x0A,0x02,0x4C,0x4E,0x4B,0x44,0x00,0x12, /* 00000530 "..LNKD.." */ + 0x0E,0x04,0x0C,0xFF,0xFF,0x05,0x00,0x0A, /* 00000538 "........" */ + 0x03,0x4C,0x4E,0x4B,0x41,0x00,0x12,0x0D, /* 00000540 ".LNKA..." */ + 0x04,0x0C,0xFF,0xFF,0x06,0x00,0x00,0x4C, /* 00000548 ".......L" */ + 0x4E,0x4B,0x43,0x00,0x12,0x0D,0x04,0x0C, /* 00000550 "NKC....." */ + 0xFF,0xFF,0x06,0x00,0x01,0x4C,0x4E,0x4B, /* 00000558 ".....LNK" */ + 0x44,0x00,0x12,0x0E,0x04,0x0C,0xFF,0xFF, /* 00000560 "D......." */ + 0x06,0x00,0x0A,0x02,0x4C,0x4E,0x4B,0x41, /* 00000568 "....LNKA" */ + 0x00,0x12,0x0E,0x04,0x0C,0xFF,0xFF,0x06, /* 00000570 "........" */ + 0x00,0x0A,0x03,0x4C,0x4E,0x4B,0x42,0x00, /* 00000578 "...LNKB." */ + 0x12,0x0D,0x04,0x0C,0xFF,0xFF,0x07,0x00, /* 00000580 "........" */ + 0x00,0x4C,0x4E,0x4B,0x44,0x00,0x12,0x0D, /* 00000588 ".LNKD..." */ + 0x04,0x0C,0xFF,0xFF,0x07,0x00,0x01,0x4C, /* 00000590 ".......L" */ + 0x4E,0x4B,0x41,0x00,0x12,0x0E,0x04,0x0C, /* 00000598 "NKA....." */ + 0xFF,0xFF,0x07,0x00,0x0A,0x02,0x4C,0x4E, /* 000005A0 "......LN" */ + 0x4B,0x42,0x00,0x12,0x0E,0x04,0x0C,0xFF, /* 000005A8 "KB......" */ + 0xFF,0x07,0x00,0x0A,0x03,0x4C,0x4E,0x4B, /* 000005B0 ".....LNK" */ + 0x43,0x00,0x12,0x0D,0x04,0x0C,0xFF,0xFF, /* 000005B8 "C......." */ + 0x08,0x00,0x00,0x4C,0x4E,0x4B,0x41,0x00, /* 000005C0 "...LNKA." */ + 0x12,0x0D,0x04,0x0C,0xFF,0xFF,0x08,0x00, /* 000005C8 "........" */ + 0x01,0x4C,0x4E,0x4B,0x42,0x00,0x12,0x0E, /* 000005D0 ".LNKB..." */ + 0x04,0x0C,0xFF,0xFF,0x08,0x00,0x0A,0x02, /* 000005D8 "........" */ + 0x4C,0x4E,0x4B,0x43,0x00,0x12,0x0E,0x04, /* 000005E0 "LNKC...." */ + 0x0C,0xFF,0xFF,0x08,0x00,0x0A,0x03,0x4C, /* 000005E8 ".......L" */ + 0x4E,0x4B,0x44,0x00,0x12,0x0D,0x04,0x0C, /* 000005F0 "NKD....." */ + 0xFF,0xFF,0x09,0x00,0x00,0x4C,0x4E,0x4B, /* 000005F8 ".....LNK" */ + 0x42,0x00,0x12,0x0D,0x04,0x0C,0xFF,0xFF, /* 00000600 "B......." */ + 0x09,0x00,0x01,0x4C,0x4E,0x4B,0x43,0x00, /* 00000608 "...LNKC." */ + 0x12,0x0E,0x04,0x0C,0xFF,0xFF,0x09,0x00, /* 00000610 "........" */ + 0x0A,0x02,0x4C,0x4E,0x4B,0x44,0x00,0x12, /* 00000618 "..LNKD.." */ + 0x0E,0x04,0x0C,0xFF,0xFF,0x09,0x00,0x0A, /* 00000620 "........" */ + 0x03,0x4C,0x4E,0x4B,0x41,0x00,0x12,0x0D, /* 00000628 ".LNKA..." */ + 0x04,0x0C,0xFF,0xFF,0x0A,0x00,0x00,0x4C, /* 00000630 ".......L" */ + 0x4E,0x4B,0x43,0x00,0x12,0x0D,0x04,0x0C, /* 00000638 "NKC....." */ + 0xFF,0xFF,0x0A,0x00,0x01,0x4C,0x4E,0x4B, /* 00000640 ".....LNK" */ + 0x44,0x00,0x12,0x0E,0x04,0x0C,0xFF,0xFF, /* 00000648 "D......." */ + 0x0A,0x00,0x0A,0x02,0x4C,0x4E,0x4B,0x41, /* 00000650 "....LNKA" */ + 0x00,0x12,0x0E,0x04,0x0C,0xFF,0xFF,0x0A, /* 00000658 "........" */ + 0x00,0x0A,0x03,0x4C,0x4E,0x4B,0x42,0x00, /* 00000660 "...LNKB." */ + 0x12,0x0D,0x04,0x0C,0xFF,0xFF,0x0B,0x00, /* 00000668 "........" */ + 0x00,0x4C,0x4E,0x4B,0x44,0x00,0x12,0x0D, /* 00000670 ".LNKD..." */ + 0x04,0x0C,0xFF,0xFF,0x0B,0x00,0x01,0x4C, /* 00000678 ".......L" */ + 0x4E,0x4B,0x41,0x00,0x12,0x0E,0x04,0x0C, /* 00000680 "NKA....." */ + 0xFF,0xFF,0x0B,0x00,0x0A,0x02,0x4C,0x4E, /* 00000688 "......LN" */ + 0x4B,0x42,0x00,0x12,0x0E,0x04,0x0C,0xFF, /* 00000690 "KB......" */ + 0xFF,0x0B,0x00,0x0A,0x03,0x4C,0x4E,0x4B, /* 00000698 ".....LNK" */ + 0x43,0x00,0x12,0x0D,0x04,0x0C,0xFF,0xFF, /* 000006A0 "C......." */ + 0x0C,0x00,0x00,0x4C,0x4E,0x4B,0x41,0x00, /* 000006A8 "...LNKA." */ + 0x12,0x0D,0x04,0x0C,0xFF,0xFF,0x0C,0x00, /* 000006B0 "........" */ + 0x01,0x4C,0x4E,0x4B,0x42,0x00,0x12,0x0E, /* 000006B8 ".LNKB..." */ + 0x04,0x0C,0xFF,0xFF,0x0C,0x00,0x0A,0x02, /* 000006C0 "........" */ + 0x4C,0x4E,0x4B,0x43,0x00,0x12,0x0E,0x04, /* 000006C8 "LNKC...." */ + 0x0C,0xFF,0xFF,0x0C,0x00,0x0A,0x03,0x4C, /* 000006D0 ".......L" */ + 0x4E,0x4B,0x44,0x00,0x12,0x0D,0x04,0x0C, /* 000006D8 "NKD....." */ + 0xFF,0xFF,0x0D,0x00,0x00,0x4C,0x4E,0x4B, /* 000006E0 ".....LNK" */ + 0x42,0x00,0x12,0x0D,0x04,0x0C,0xFF,0xFF, /* 000006E8 "B......." */ + 0x0D,0x00,0x01,0x4C,0x4E,0x4B,0x43,0x00, /* 000006F0 "...LNKC." */ + 0x12,0x0E,0x04,0x0C,0xFF,0xFF,0x0D,0x00, /* 000006F8 "........" */ + 0x0A,0x02,0x4C,0x4E,0x4B,0x44,0x00,0x12, /* 00000700 "..LNKD.." */ + 0x0E,0x04,0x0C,0xFF,0xFF,0x0D,0x00,0x0A, /* 00000708 "........" */ + 0x03,0x4C,0x4E,0x4B,0x41,0x00,0x12,0x0D, /* 00000710 ".LNKA..." */ + 0x04,0x0C,0xFF,0xFF,0x0E,0x00,0x00,0x4C, /* 00000718 ".......L" */ + 0x4E,0x4B,0x43,0x00,0x12,0x0D,0x04,0x0C, /* 00000720 "NKC....." */ + 0xFF,0xFF,0x0E,0x00,0x01,0x4C,0x4E,0x4B, /* 00000728 ".....LNK" */ + 0x44,0x00,0x12,0x0E,0x04,0x0C,0xFF,0xFF, /* 00000730 "D......." */ + 0x0E,0x00,0x0A,0x02,0x4C,0x4E,0x4B,0x41, /* 00000738 "....LNKA" */ + 0x00,0x12,0x0E,0x04,0x0C,0xFF,0xFF,0x0E, /* 00000740 "........" */ + 0x00,0x0A,0x03,0x4C,0x4E,0x4B,0x42,0x00, /* 00000748 "...LNKB." */ + 0x12,0x0D,0x04,0x0C,0xFF,0xFF,0x0F,0x00, /* 00000750 "........" */ + 0x00,0x4C,0x4E,0x4B,0x44,0x00,0x12,0x0D, /* 00000758 ".LNKD..." */ + 0x04,0x0C,0xFF,0xFF,0x0F,0x00,0x01,0x4C, /* 00000760 ".......L" */ + 0x4E,0x4B,0x41,0x00,0x12,0x0E,0x04,0x0C, /* 00000768 "NKA....." */ + 0xFF,0xFF,0x0F,0x00,0x0A,0x02,0x4C,0x4E, /* 00000770 "......LN" */ + 0x4B,0x42,0x00,0x12,0x0E,0x04,0x0C,0xFF, /* 00000778 "KB......" */ + 0xFF,0x0F,0x00,0x0A,0x03,0x4C,0x4E,0x4B, /* 00000780 ".....LNK" */ + 0x43,0x00,0x08,0x50,0x52,0x54,0x41,0x12, /* 00000788 "C..PRTA." */ + 0x41,0x2F,0x3C,0x12,0x0B,0x04,0x0C,0xFF, /* 00000790 "A/<....." */ + 0xFF,0x01,0x00,0x00,0x00,0x0A,0x14,0x12, /* 00000798 "........" */ + 0x0B,0x04,0x0C,0xFF,0xFF,0x01,0x00,0x01, /* 000007A0 "........" */ + 0x00,0x0A,0x15,0x12,0x0C,0x04,0x0C,0xFF, /* 000007A8 "........" */ + 0xFF,0x01,0x00,0x0A,0x02,0x00,0x0A,0x16, /* 000007B0 "........" */ + 0x12,0x0C,0x04,0x0C,0xFF,0xFF,0x01,0x00, /* 000007B8 "........" */ + 0x0A,0x03,0x00,0x0A,0x17,0x12,0x0B,0x04, /* 000007C0 "........" */ + 0x0C,0xFF,0xFF,0x02,0x00,0x00,0x00,0x0A, /* 000007C8 "........" */ + 0x18,0x12,0x0B,0x04,0x0C,0xFF,0xFF,0x02, /* 000007D0 "........" */ + 0x00,0x01,0x00,0x0A,0x19,0x12,0x0C,0x04, /* 000007D8 "........" */ + 0x0C,0xFF,0xFF,0x02,0x00,0x0A,0x02,0x00, /* 000007E0 "........" */ + 0x0A,0x1A,0x12,0x0C,0x04,0x0C,0xFF,0xFF, /* 000007E8 "........" */ + 0x02,0x00,0x0A,0x03,0x00,0x0A,0x1B,0x12, /* 000007F0 "........" */ + 0x0B,0x04,0x0C,0xFF,0xFF,0x03,0x00,0x00, /* 000007F8 "........" */ + 0x00,0x0A,0x1C,0x12,0x0B,0x04,0x0C,0xFF, /* 00000800 "........" */ + 0xFF,0x03,0x00,0x01,0x00,0x0A,0x1D,0x12, /* 00000808 "........" */ + 0x0C,0x04,0x0C,0xFF,0xFF,0x03,0x00,0x0A, /* 00000810 "........" */ + 0x02,0x00,0x0A,0x1E,0x12,0x0C,0x04,0x0C, /* 00000818 "........" */ + 0xFF,0xFF,0x03,0x00,0x0A,0x03,0x00,0x0A, /* 00000820 "........" */ + 0x1F,0x12,0x0B,0x04,0x0C,0xFF,0xFF,0x04, /* 00000828 "........" */ + 0x00,0x00,0x00,0x0A,0x20,0x12,0x0B,0x04, /* 00000830 ".... ..." */ + 0x0C,0xFF,0xFF,0x04,0x00,0x01,0x00,0x0A, /* 00000838 "........" */ + 0x21,0x12,0x0C,0x04,0x0C,0xFF,0xFF,0x04, /* 00000840 "!......." */ + 0x00,0x0A,0x02,0x00,0x0A,0x22,0x12,0x0C, /* 00000848 ".....".." */ + 0x04,0x0C,0xFF,0xFF,0x04,0x00,0x0A,0x03, /* 00000850 "........" */ + 0x00,0x0A,0x23,0x12,0x0B,0x04,0x0C,0xFF, /* 00000858 "..#....." */ + 0xFF,0x05,0x00,0x00,0x00,0x0A,0x24,0x12, /* 00000860 "......$." */ + 0x0B,0x04,0x0C,0xFF,0xFF,0x05,0x00,0x01, /* 00000868 "........" */ + 0x00,0x0A,0x25,0x12,0x0C,0x04,0x0C,0xFF, /* 00000870 "..%....." */ + 0xFF,0x05,0x00,0x0A,0x02,0x00,0x0A,0x26, /* 00000878 ".......&" */ + 0x12,0x0C,0x04,0x0C,0xFF,0xFF,0x05,0x00, /* 00000880 "........" */ + 0x0A,0x03,0x00,0x0A,0x27,0x12,0x0B,0x04, /* 00000888 "....'..." */ + 0x0C,0xFF,0xFF,0x06,0x00,0x00,0x00,0x0A, /* 00000890 "........" */ + 0x28,0x12,0x0B,0x04,0x0C,0xFF,0xFF,0x06, /* 00000898 "(......." */ + 0x00,0x01,0x00,0x0A,0x29,0x12,0x0C,0x04, /* 000008A0 "....)..." */ + 0x0C,0xFF,0xFF,0x06,0x00,0x0A,0x02,0x00, /* 000008A8 "........" */ + 0x0A,0x2A,0x12,0x0C,0x04,0x0C,0xFF,0xFF, /* 000008B0 ".*......" */ + 0x06,0x00,0x0A,0x03,0x00,0x0A,0x2B,0x12, /* 000008B8 "......+." */ + 0x0B,0x04,0x0C,0xFF,0xFF,0x07,0x00,0x00, /* 000008C0 "........" */ + 0x00,0x0A,0x2C,0x12,0x0B,0x04,0x0C,0xFF, /* 000008C8 "..,....." */ + 0xFF,0x07,0x00,0x01,0x00,0x0A,0x2D,0x12, /* 000008D0 "......-." */ + 0x0C,0x04,0x0C,0xFF,0xFF,0x07,0x00,0x0A, /* 000008D8 "........" */ + 0x02,0x00,0x0A,0x2E,0x12,0x0C,0x04,0x0C, /* 000008E0 "........" */ + 0xFF,0xFF,0x07,0x00,0x0A,0x03,0x00,0x0A, /* 000008E8 "........" */ + 0x2F,0x12,0x0B,0x04,0x0C,0xFF,0xFF,0x08, /* 000008F0 "/......." */ + 0x00,0x00,0x00,0x0A,0x11,0x12,0x0B,0x04, /* 000008F8 "........" */ + 0x0C,0xFF,0xFF,0x08,0x00,0x01,0x00,0x0A, /* 00000900 "........" */ + 0x12,0x12,0x0C,0x04,0x0C,0xFF,0xFF,0x08, /* 00000908 "........" */ + 0x00,0x0A,0x02,0x00,0x0A,0x13,0x12,0x0C, /* 00000910 "........" */ + 0x04,0x0C,0xFF,0xFF,0x08,0x00,0x0A,0x03, /* 00000918 "........" */ + 0x00,0x0A,0x14,0x12,0x0B,0x04,0x0C,0xFF, /* 00000920 "........" */ + 0xFF,0x09,0x00,0x00,0x00,0x0A,0x15,0x12, /* 00000928 "........" */ + 0x0B,0x04,0x0C,0xFF,0xFF,0x09,0x00,0x01, /* 00000930 "........" */ + 0x00,0x0A,0x16,0x12,0x0C,0x04,0x0C,0xFF, /* 00000938 "........" */ + 0xFF,0x09,0x00,0x0A,0x02,0x00,0x0A,0x17, /* 00000940 "........" */ + 0x12,0x0C,0x04,0x0C,0xFF,0xFF,0x09,0x00, /* 00000948 "........" */ + 0x0A,0x03,0x00,0x0A,0x18,0x12,0x0B,0x04, /* 00000950 "........" */ + 0x0C,0xFF,0xFF,0x0A,0x00,0x00,0x00,0x0A, /* 00000958 "........" */ + 0x19,0x12,0x0B,0x04,0x0C,0xFF,0xFF,0x0A, /* 00000960 "........" */ + 0x00,0x01,0x00,0x0A,0x1A,0x12,0x0C,0x04, /* 00000968 "........" */ + 0x0C,0xFF,0xFF,0x0A,0x00,0x0A,0x02,0x00, /* 00000970 "........" */ + 0x0A,0x1B,0x12,0x0C,0x04,0x0C,0xFF,0xFF, /* 00000978 "........" */ + 0x0A,0x00,0x0A,0x03,0x00,0x0A,0x1C,0x12, /* 00000980 "........" */ + 0x0B,0x04,0x0C,0xFF,0xFF,0x0B,0x00,0x00, /* 00000988 "........" */ + 0x00,0x0A,0x1D,0x12,0x0B,0x04,0x0C,0xFF, /* 00000990 "........" */ + 0xFF,0x0B,0x00,0x01,0x00,0x0A,0x1E,0x12, /* 00000998 "........" */ + 0x0C,0x04,0x0C,0xFF,0xFF,0x0B,0x00,0x0A, /* 000009A0 "........" */ + 0x02,0x00,0x0A,0x1F,0x12,0x0C,0x04,0x0C, /* 000009A8 "........" */ + 0xFF,0xFF,0x0B,0x00,0x0A,0x03,0x00,0x0A, /* 000009B0 "........" */ + 0x20,0x12,0x0B,0x04,0x0C,0xFF,0xFF,0x0C, /* 000009B8 " ......." */ + 0x00,0x00,0x00,0x0A,0x21,0x12,0x0B,0x04, /* 000009C0 "....!..." */ + 0x0C,0xFF,0xFF,0x0C,0x00,0x01,0x00,0x0A, /* 000009C8 "........" */ + 0x22,0x12,0x0C,0x04,0x0C,0xFF,0xFF,0x0C, /* 000009D0 ""......." */ + 0x00,0x0A,0x02,0x00,0x0A,0x23,0x12,0x0C, /* 000009D8 ".....#.." */ + 0x04,0x0C,0xFF,0xFF,0x0C,0x00,0x0A,0x03, /* 000009E0 "........" */ + 0x00,0x0A,0x24,0x12,0x0B,0x04,0x0C,0xFF, /* 000009E8 "..$....." */ + 0xFF,0x0D,0x00,0x00,0x00,0x0A,0x25,0x12, /* 000009F0 "......%." */ + 0x0B,0x04,0x0C,0xFF,0xFF,0x0D,0x00,0x01, /* 000009F8 "........" */ + 0x00,0x0A,0x26,0x12,0x0C,0x04,0x0C,0xFF, /* 00000A00 "..&....." */ + 0xFF,0x0D,0x00,0x0A,0x02,0x00,0x0A,0x27, /* 00000A08 ".......'" */ + 0x12,0x0C,0x04,0x0C,0xFF,0xFF,0x0D,0x00, /* 00000A10 "........" */ + 0x0A,0x03,0x00,0x0A,0x28,0x12,0x0B,0x04, /* 00000A18 "....(..." */ + 0x0C,0xFF,0xFF,0x0E,0x00,0x00,0x00,0x0A, /* 00000A20 "........" */ + 0x29,0x12,0x0B,0x04,0x0C,0xFF,0xFF,0x0E, /* 00000A28 ")......." */ + 0x00,0x01,0x00,0x0A,0x2A,0x12,0x0C,0x04, /* 00000A30 "....*..." */ + 0x0C,0xFF,0xFF,0x0E,0x00,0x0A,0x02,0x00, /* 00000A38 "........" */ + 0x0A,0x2B,0x12,0x0C,0x04,0x0C,0xFF,0xFF, /* 00000A40 ".+......" */ + 0x0E,0x00,0x0A,0x03,0x00,0x0A,0x2C,0x12, /* 00000A48 "......,." */ + 0x0B,0x04,0x0C,0xFF,0xFF,0x0F,0x00,0x00, /* 00000A50 "........" */ + 0x00,0x0A,0x2D,0x12,0x0B,0x04,0x0C,0xFF, /* 00000A58 "..-....." */ + 0xFF,0x0F,0x00,0x01,0x00,0x0A,0x2E,0x12, /* 00000A60 "........" */ + 0x0C,0x04,0x0C,0xFF,0xFF,0x0F,0x00,0x0A, /* 00000A68 "........" */ + 0x02,0x00,0x0A,0x2F,0x12,0x0C,0x04,0x0C, /* 00000A70 ".../...." */ + 0xFF,0xFF,0x0F,0x00,0x0A,0x03,0x00,0x0A, /* 00000A78 "........" */ + 0x10,0x5B,0x82,0x4C,0x31,0x49,0x53,0x41, /* 00000A80 ".[.L1ISA" */ + 0x5F,0x08,0x5F,0x41,0x44,0x52,0x0C,0x00, /* 00000A88 "_._ADR.." */ + 0x00,0x01,0x00,0x5B,0x80,0x50,0x49,0x52, /* 00000A90 "...[.PIR" */ + 0x51,0x02,0x0A,0x60,0x0A,0x04,0x10,0x2E, /* 00000A98 "Q..`...." */ + 0x5C,0x00,0x5B,0x81,0x29,0x5C,0x2F,0x04, /* 00000AA0 "\.[.)\/." */ + 0x5F,0x53,0x42,0x5F,0x50,0x43,0x49,0x30, /* 00000AA8 "_SB_PCI0" */ + 0x49,0x53,0x41,0x5F,0x50,0x49,0x52,0x51, /* 00000AB0 "ISA_PIRQ" */ + 0x01,0x50,0x49,0x52,0x41,0x08,0x50,0x49, /* 00000AB8 ".PIRA.PI" */ + 0x52,0x42,0x08,0x50,0x49,0x52,0x43,0x08, /* 00000AC0 "RB.PIRC." */ + 0x50,0x49,0x52,0x44,0x08,0x5B,0x82,0x46, /* 00000AC8 "PIRD.[.F" */ + 0x0B,0x53,0x59,0x53,0x52,0x08,0x5F,0x48, /* 00000AD0 ".SYSR._H" */ + 0x49,0x44,0x0C,0x41,0xD0,0x0C,0x02,0x08, /* 00000AD8 "ID.A...." */ + 0x5F,0x55,0x49,0x44,0x01,0x08,0x43,0x52, /* 00000AE0 "_UID..CR" */ + 0x53,0x5F,0x11,0x4E,0x08,0x0A,0x8A,0x47, /* 00000AE8 "S_.N...G" */ + 0x01,0x10,0x00,0x10,0x00,0x00,0x10,0x47, /* 00000AF0 ".......G" */ + 0x01,0x22,0x00,0x22,0x00,0x00,0x0C,0x47, /* 00000AF8 "."."...G" */ + 0x01,0x30,0x00,0x30,0x00,0x00,0x10,0x47, /* 00000B00 ".0.0...G" */ + 0x01,0x44,0x00,0x44,0x00,0x00,0x1C,0x47, /* 00000B08 ".D.D...G" */ + 0x01,0x62,0x00,0x62,0x00,0x00,0x02,0x47, /* 00000B10 ".b.b...G" */ + 0x01,0x65,0x00,0x65,0x00,0x00,0x0B,0x47, /* 00000B18 ".e.e...G" */ + 0x01,0x72,0x00,0x72,0x00,0x00,0x0E,0x47, /* 00000B20 ".r.r...G" */ + 0x01,0x80,0x00,0x80,0x00,0x00,0x01,0x47, /* 00000B28 ".......G" */ + 0x01,0x84,0x00,0x84,0x00,0x00,0x03,0x47, /* 00000B30 ".......G" */ + 0x01,0x88,0x00,0x88,0x00,0x00,0x01,0x47, /* 00000B38 ".......G" */ + 0x01,0x8C,0x00,0x8C,0x00,0x00,0x03,0x47, /* 00000B40 ".......G" */ + 0x01,0x90,0x00,0x90,0x00,0x00,0x10,0x47, /* 00000B48 ".......G" */ + 0x01,0xA2,0x00,0xA2,0x00,0x00,0x1C,0x47, /* 00000B50 ".......G" */ + 0x01,0xE0,0x00,0xE0,0x00,0x00,0x10,0x47, /* 00000B58 ".......G" */ + 0x01,0xA0,0x08,0xA0,0x08,0x00,0x04,0x47, /* 00000B60 ".......G" */ + 0x01,0xC0,0x0C,0xC0,0x0C,0x00,0x10,0x47, /* 00000B68 ".......G" */ + 0x01,0xD0,0x04,0xD0,0x04,0x00,0x02,0x79, /* 00000B70 ".......y" */ + 0x00,0x14,0x0B,0x5F,0x43,0x52,0x53,0x00, /* 00000B78 "..._CRS." */ + 0xA4,0x43,0x52,0x53,0x5F,0x5B,0x82,0x2B, /* 00000B80 ".CRS_[.+" */ + 0x50,0x49,0x43,0x5F,0x08,0x5F,0x48,0x49, /* 00000B88 "PIC_._HI" */ + 0x44,0x0B,0x41,0xD0,0x08,0x5F,0x43,0x52, /* 00000B90 "D.A.._CR" */ + 0x53,0x11,0x18,0x0A,0x15,0x47,0x01,0x20, /* 00000B98 "S....G. " */ + 0x00,0x20,0x00,0x01,0x02,0x47,0x01,0xA0, /* 00000BA0 ". ...G.." */ + 0x00,0xA0,0x00,0x01,0x02,0x22,0x04,0x00, /* 00000BA8 ".....".." */ + 0x79,0x00,0x5B,0x82,0x47,0x05,0x44,0x4D, /* 00000BB0 "y.[.G.DM" */ + 0x41,0x30,0x08,0x5F,0x48,0x49,0x44,0x0C, /* 00000BB8 "A0._HID." */ + 0x41,0xD0,0x02,0x00,0x08,0x5F,0x43,0x52, /* 00000BC0 "A...._CR" */ + 0x53,0x11,0x41,0x04,0x0A,0x3D,0x2A,0x10, /* 00000BC8 "S.A..=*." */ + 0x04,0x47,0x01,0x00,0x00,0x00,0x00,0x00, /* 00000BD0 ".G......" */ + 0x10,0x47,0x01,0x81,0x00,0x81,0x00,0x00, /* 00000BD8 ".G......" */ + 0x03,0x47,0x01,0x87,0x00,0x87,0x00,0x00, /* 00000BE0 ".G......" */ + 0x01,0x47,0x01,0x89,0x00,0x89,0x00,0x00, /* 00000BE8 ".G......" */ + 0x03,0x47,0x01,0x8F,0x00,0x8F,0x00,0x00, /* 00000BF0 ".G......" */ + 0x01,0x47,0x01,0xC0,0x00,0xC0,0x00,0x00, /* 00000BF8 ".G......" */ + 0x20,0x47,0x01,0x80,0x04,0x80,0x04,0x00, /* 00000C00 " G......" */ + 0x10,0x79,0x00,0x5B,0x82,0x25,0x54,0x4D, /* 00000C08 ".y.[.%TM" */ + 0x52,0x5F,0x08,0x5F,0x48,0x49,0x44,0x0C, /* 00000C10 "R_._HID." */ + 0x41,0xD0,0x01,0x00,0x08,0x5F,0x43,0x52, /* 00000C18 "A...._CR" */ + 0x53,0x11,0x10,0x0A,0x0D,0x47,0x01,0x40, /* 00000C20 "S....G.@" */ + 0x00,0x40,0x00,0x00,0x04,0x22,0x01,0x00, /* 00000C28 ".@...".." */ + 0x79,0x00,0x5B,0x82,0x25,0x52,0x54,0x43, /* 00000C30 "y.[.%RTC" */ + 0x5F,0x08,0x5F,0x48,0x49,0x44,0x0C,0x41, /* 00000C38 "_._HID.A" */ + 0xD0,0x0B,0x00,0x08,0x5F,0x43,0x52,0x53, /* 00000C40 "...._CRS" */ + 0x11,0x10,0x0A,0x0D,0x47,0x01,0x70,0x00, /* 00000C48 "....G.p." */ + 0x70,0x00,0x00,0x02,0x22,0x00,0x01,0x79, /* 00000C50 "p..."..y" */ + 0x00,0x5B,0x82,0x22,0x53,0x50,0x4B,0x52, /* 00000C58 ".[."SPKR" */ + 0x08,0x5F,0x48,0x49,0x44,0x0C,0x41,0xD0, /* 00000C60 "._HID.A." */ + 0x08,0x00,0x08,0x5F,0x43,0x52,0x53,0x11, /* 00000C68 "..._CRS." */ + 0x0D,0x0A,0x0A,0x47,0x01,0x61,0x00,0x61, /* 00000C70 "...G.a.a" */ + 0x00,0x00,0x01,0x79,0x00,0x5B,0x82,0x31, /* 00000C78 "...y.[.1" */ + 0x50,0x53,0x32,0x4D,0x08,0x5F,0x48,0x49, /* 00000C80 "PS2M._HI" */ + 0x44,0x0C,0x41,0xD0,0x0F,0x13,0x08,0x5F, /* 00000C88 "D.A...._" */ + 0x43,0x49,0x44,0x0C,0x41,0xD0,0x0F,0x13, /* 00000C90 "CID.A..." */ + 0x14,0x09,0x5F,0x53,0x54,0x41,0x00,0xA4, /* 00000C98 ".._STA.." */ + 0x0A,0x0F,0x08,0x5F,0x43,0x52,0x53,0x11, /* 00000CA0 "..._CRS." */ + 0x08,0x0A,0x05,0x22,0x00,0x10,0x79,0x00, /* 00000CA8 "..."..y." */ + 0x5B,0x82,0x42,0x04,0x50,0x53,0x32,0x4B, /* 00000CB0 "[.B.PS2K" */ + 0x08,0x5F,0x48,0x49,0x44,0x0C,0x41,0xD0, /* 00000CB8 "._HID.A." */ + 0x03,0x03,0x08,0x5F,0x43,0x49,0x44,0x0C, /* 00000CC0 "..._CID." */ + 0x41,0xD0,0x03,0x0B,0x14,0x09,0x5F,0x53, /* 00000CC8 "A....._S" */ + 0x54,0x41,0x00,0xA4,0x0A,0x0F,0x08,0x5F, /* 00000CD0 "TA....._" */ + 0x43,0x52,0x53,0x11,0x18,0x0A,0x15,0x47, /* 00000CD8 "CRS....G" */ + 0x01,0x60,0x00,0x60,0x00,0x00,0x01,0x47, /* 00000CE0 ".`.`...G" */ + 0x01,0x64,0x00,0x64,0x00,0x00,0x01,0x22, /* 00000CE8 ".d.d..."" */ + 0x02,0x00,0x79,0x00,0x5B,0x82,0x3A,0x46, /* 00000CF0 "..y.[.:F" */ + 0x44,0x43,0x30,0x08,0x5F,0x48,0x49,0x44, /* 00000CF8 "DC0._HID" */ + 0x0C,0x41,0xD0,0x07,0x00,0x14,0x09,0x5F, /* 00000D00 ".A....._" */ + 0x53,0x54,0x41,0x00,0xA4,0x0A,0x0F,0x08, /* 00000D08 "STA....." */ + 0x5F,0x43,0x52,0x53,0x11,0x1B,0x0A,0x18, /* 00000D10 "_CRS...." */ + 0x47,0x01,0xF0,0x03,0xF0,0x03,0x01,0x06, /* 00000D18 "G......." */ + 0x47,0x01,0xF7,0x03,0xF7,0x03,0x01,0x01, /* 00000D20 "G......." */ + 0x22,0x40,0x00,0x2A,0x04,0x00,0x79,0x00, /* 00000D28 ""@.*..y." */ + 0x5B,0x82,0x35,0x55,0x41,0x52,0x31,0x08, /* 00000D30 "[.5UAR1." */ + 0x5F,0x48,0x49,0x44,0x0C,0x41,0xD0,0x05, /* 00000D38 "_HID.A.." */ + 0x01,0x08,0x5F,0x55,0x49,0x44,0x01,0x14, /* 00000D40 ".._UID.." */ + 0x09,0x5F,0x53,0x54,0x41,0x00,0xA4,0x0A, /* 00000D48 "._STA..." */ + 0x0F,0x08,0x5F,0x43,0x52,0x53,0x11,0x10, /* 00000D50 ".._CRS.." */ + 0x0A,0x0D,0x47,0x01,0xF8,0x03,0xF8,0x03, /* 00000D58 "..G....." */ + 0x01,0x08,0x22,0x10,0x00,0x79,0x00,0x5B, /* 00000D60 ".."..y.[" */ + 0x82,0x36,0x4C,0x54,0x50,0x31,0x08,0x5F, /* 00000D68 ".6LTP1._" */ + 0x48,0x49,0x44,0x0C,0x41,0xD0,0x04,0x00, /* 00000D70 "HID.A..." */ + 0x08,0x5F,0x55,0x49,0x44,0x0A,0x02,0x14, /* 00000D78 "._UID..." */ + 0x09,0x5F,0x53,0x54,0x41,0x00,0xA4,0x0A, /* 00000D80 "._STA..." */ + 0x0F,0x08,0x5F,0x43,0x52,0x53,0x11,0x10, /* 00000D88 ".._CRS.." */ + 0x0A,0x0D,0x47,0x01,0x78,0x03,0x78,0x03, /* 00000D90 "..G.x.x." */ + 0x08,0x08,0x22,0x80,0x00,0x79,0x00, }; int DsdtLen=sizeof(AmlCode); diff -r 04c23c1ef888 -r d907467f08cd tools/firmware/rombios/32bit/Makefile --- a/tools/firmware/rombios/32bit/Makefile Sun Feb 18 16:13:13 2007 -0700 +++ b/tools/firmware/rombios/32bit/Makefile Tue Feb 20 12:58:22 2007 -0700 @@ -9,6 +9,8 @@ TARGET = 32bitbios_flat.h CFLAGS += -fno-builtin -O2 -msoft-float -nostdlib CFLAGS += -I../ -DGCC_PROTOS +CFLAGS += $(call cc-option,$(CC),-fno-stack-protector,) +CFLAGS += $(call cc-option,$(CC),-fno-stack-protector-all,) SUBDIRS = tcgbios diff -r 04c23c1ef888 -r d907467f08cd tools/firmware/rombios/32bit/tcgbios/Makefile --- a/tools/firmware/rombios/32bit/tcgbios/Makefile Sun Feb 18 16:13:13 2007 -0700 +++ b/tools/firmware/rombios/32bit/tcgbios/Makefile Tue Feb 20 12:58:22 2007 -0700 @@ -9,6 +9,8 @@ OBJECTS = $(foreach f,$(FILES),$(f).o) OBJECTS = $(foreach f,$(FILES),$(f).o) CFLAGS += -fno-builtin -O2 -msoft-float -nostdlib +CFLAGS += $(call cc-option,$(CC),-fno-stack-protector,) +CFLAGS += $(call cc-option,$(CC),-fno-stack-protector-all,) CFLAGS += -I../ -I../../ -DGCC_PROTOS .PHONY: all clean diff -r 04c23c1ef888 -r d907467f08cd tools/ioemu/hw/tpm_tis.c --- a/tools/ioemu/hw/tpm_tis.c Sun Feb 18 16:13:13 2007 -0700 +++ b/tools/ioemu/hw/tpm_tis.c Tue Feb 20 12:58:22 2007 -0700 @@ -769,6 +769,8 @@ static void tpm_save(QEMUFile* f,void* o if (n > 0) { if (IS_VALID_LOC(s->active_loc)) { s->loc[s->active_loc].sts = STS_VALID | STS_DATA_AVAILABLE; + s->loc[s->active_loc].state = STATE_COMPLETION; + tis_raise_irq(s, s->active_loc, INT_DATA_AVAILABLE); } /* close the connection with the vTPM for good */ close_vtpm_channel(s, 1); @@ -881,6 +883,7 @@ void tpm_tis_init(SetIRQFunc *set_irq, v s->Transmitlayer = -1; s->tpmTx.fd[0] = -1; s->tpmTx.fd[1] = -1; + s->aborting_locty = NO_LOCALITY; tpm_initialize_instance(s, s->vtpm_instance); memset(s->buffer.buf,0,sizeof(s->buffer.buf)); diff -r 04c23c1ef888 -r d907467f08cd tools/libfsimage/common/fsimage.c --- a/tools/libfsimage/common/fsimage.c Sun Feb 18 16:13:13 2007 -0700 +++ b/tools/libfsimage/common/fsimage.c Tue Feb 20 12:58:22 2007 -0700 @@ -36,7 +36,7 @@ static pthread_mutex_t fsi_lock = PTHREAD_MUTEX_INITIALIZER; -fsi_t *fsi_open_fsimage(const char *path, uint64_t off) +fsi_t *fsi_open_fsimage(const char *path, uint64_t off, const char *options) { fsi_t *fsi = NULL; int fd; @@ -53,7 +53,7 @@ fsi_t *fsi_open_fsimage(const char *path fsi->f_data = NULL; pthread_mutex_lock(&fsi_lock); - err = find_plugin(fsi, path); + err = find_plugin(fsi, path, options); pthread_mutex_unlock(&fsi_lock); if (err != 0) goto fail; diff -r 04c23c1ef888 -r d907467f08cd tools/libfsimage/common/fsimage.h --- a/tools/libfsimage/common/fsimage.h Sun Feb 18 16:13:13 2007 -0700 +++ b/tools/libfsimage/common/fsimage.h Tue Feb 20 12:58:22 2007 -0700 @@ -35,7 +35,7 @@ typedef struct fsi fsi_t; typedef struct fsi fsi_t; typedef struct fsi_file fsi_file_t; -fsi_t *fsi_open_fsimage(const char *, uint64_t); +fsi_t *fsi_open_fsimage(const char *, uint64_t, const char *); void fsi_close_fsimage(fsi_t *); int fsi_file_exists(fsi_t *, const char *); diff -r 04c23c1ef888 -r d907467f08cd tools/libfsimage/common/fsimage_grub.c --- a/tools/libfsimage/common/fsimage_grub.c Sun Feb 18 16:13:13 2007 -0700 +++ b/tools/libfsimage/common/fsimage_grub.c Tue Feb 20 12:58:22 2007 -0700 @@ -161,7 +161,7 @@ fsig_substring(const char *s1, const cha } static int -fsig_mount(fsi_t *fsi, const char *path) +fsig_mount(fsi_t *fsi, const char *path, const char *options) { fsig_plugin_ops_t *ops = fsi->f_plugin->fp_data; fsi_file_t *ffi; @@ -178,7 +178,7 @@ fsig_mount(fsi_t *fsi, const char *path) bzero(fsi->f_data, sizeof (fsig_data_t)); - if (!ops->fpo_mount(ffi)) { + if (!ops->fpo_mount(ffi, options)) { fsip_file_free(ffi); free(fsi->f_data); fsi->f_data = NULL; diff -r 04c23c1ef888 -r d907467f08cd tools/libfsimage/common/fsimage_grub.h --- a/tools/libfsimage/common/fsimage_grub.h Sun Feb 18 16:13:13 2007 -0700 +++ b/tools/libfsimage/common/fsimage_grub.h Tue Feb 20 12:58:22 2007 -0700 @@ -38,7 +38,7 @@ extern C { typedef struct fsig_plugin_ops { int fpo_version; - int (*fpo_mount)(fsi_file_t *); + int (*fpo_mount)(fsi_file_t *, const char *); int (*fpo_dir)(fsi_file_t *, char *); int (*fpo_read)(fsi_file_t *, char *, int); } fsig_plugin_ops_t; diff -r 04c23c1ef888 -r d907467f08cd tools/libfsimage/common/fsimage_plugin.c --- a/tools/libfsimage/common/fsimage_plugin.c Sun Feb 18 16:13:13 2007 -0700 +++ b/tools/libfsimage/common/fsimage_plugin.c Tue Feb 20 12:58:22 2007 -0700 @@ -185,7 +185,7 @@ fail: return (ret); } -int find_plugin(fsi_t *fsi, const char *path) +int find_plugin(fsi_t *fsi, const char *path, const char *options) { fsi_plugin_t *fp; int ret = 0; @@ -195,7 +195,7 @@ int find_plugin(fsi_t *fsi, const char * for (fp = plugins; fp != NULL; fp = fp->fp_next) { fsi->f_plugin = fp; - if (fp->fp_ops->fpo_mount(fsi, path) == 0) + if (fp->fp_ops->fpo_mount(fsi, path, options) == 0) goto out; } diff -r 04c23c1ef888 -r d907467f08cd tools/libfsimage/common/fsimage_plugin.h --- a/tools/libfsimage/common/fsimage_plugin.h Sun Feb 18 16:13:13 2007 -0700 +++ b/tools/libfsimage/common/fsimage_plugin.h Tue Feb 20 12:58:22 2007 -0700 @@ -38,7 +38,7 @@ typedef struct fsi_plugin fsi_plugin_t; typedef struct fsi_plugin_ops { int fpo_version; - int (*fpo_mount)(fsi_t *, const char *); + int (*fpo_mount)(fsi_t *, const char *, const char *); int (*fpo_umount)(fsi_t *); fsi_file_t *(*fpo_open)(fsi_t *, const char *); ssize_t (*fpo_read)(fsi_file_t *, void *, size_t); diff -r 04c23c1ef888 -r d907467f08cd tools/libfsimage/common/fsimage_priv.h --- a/tools/libfsimage/common/fsimage_priv.h Sun Feb 18 16:13:13 2007 -0700 +++ b/tools/libfsimage/common/fsimage_priv.h Tue Feb 20 12:58:22 2007 -0700 @@ -53,7 +53,7 @@ struct fsi_file { void *ff_data; }; -int find_plugin(fsi_t *, const char *); +int find_plugin(fsi_t *, const char *, const char *); #ifdef __cplusplus }; diff -r 04c23c1ef888 -r d907467f08cd tools/libfsimage/ext2fs-lib/ext2fs-lib.c --- a/tools/libfsimage/ext2fs-lib/ext2fs-lib.c Sun Feb 18 16:13:13 2007 -0700 +++ b/tools/libfsimage/ext2fs-lib/ext2fs-lib.c Tue Feb 20 12:58:22 2007 -0700 @@ -27,7 +27,7 @@ #include <inttypes.h> static int -ext2lib_mount(fsi_t *fsi, const char *name) +ext2lib_mount(fsi_t *fsi, const char *name, const char *options) { int err; char opts[30] = ""; diff -r 04c23c1ef888 -r d907467f08cd tools/libfsimage/ext2fs/fsys_ext2fs.c --- a/tools/libfsimage/ext2fs/fsys_ext2fs.c Sun Feb 18 16:13:13 2007 -0700 +++ b/tools/libfsimage/ext2fs/fsys_ext2fs.c Tue Feb 20 12:58:22 2007 -0700 @@ -321,7 +321,7 @@ ffz (unsigned long word) /* check filesystem types and read superblock into memory buffer */ int -ext2fs_mount (fsi_file_t *ffi) +ext2fs_mount (fsi_file_t *ffi, const char *options) { int retval = 1; diff -r 04c23c1ef888 -r d907467f08cd tools/libfsimage/reiserfs/fsys_reiserfs.c --- a/tools/libfsimage/reiserfs/fsys_reiserfs.c Sun Feb 18 16:13:13 2007 -0700 +++ b/tools/libfsimage/reiserfs/fsys_reiserfs.c Tue Feb 20 12:58:22 2007 -0700 @@ -633,7 +633,7 @@ journal_init (fsi_file_t *ffi) /* check filesystem types and read superblock into memory buffer */ int -reiserfs_mount (fsi_file_t *ffi) +reiserfs_mount (fsi_file_t *ffi, const char *options) { struct reiserfs_super_block super; int superblock = REISERFS_DISK_OFFSET_IN_BYTES >> SECTOR_BITS; diff -r 04c23c1ef888 -r d907467f08cd tools/libfsimage/ufs/fsys_ufs.c --- a/tools/libfsimage/ufs/fsys_ufs.c Sun Feb 18 16:13:13 2007 -0700 +++ b/tools/libfsimage/ufs/fsys_ufs.c Tue Feb 20 12:58:22 2007 -0700 @@ -44,7 +44,7 @@ static grub_daddr32_t sbmap(fsi_file_t * /* read superblock and check fs magic */ int -ufs_mount(fsi_file_t *ffi) +ufs_mount(fsi_file_t *ffi, const char *options) { if (/*! IS_PC_SLICE_TYPE_SOLARIS(current_slice) || */ !devread(ffi, UFS_SBLOCK, 0, UFS_SBSIZE, (char *)SUPERBLOCK) || diff -r 04c23c1ef888 -r d907467f08cd tools/libxc/Makefile --- a/tools/libxc/Makefile Sun Feb 18 16:13:13 2007 -0700 +++ b/tools/libxc/Makefile Tue Feb 20 12:58:22 2007 -0700 @@ -22,11 +22,7 @@ CTRL_SRCS-$(CONFIG_X86_Linux) += xc_ptra CTRL_SRCS-$(CONFIG_X86_Linux) += xc_ptrace.c xc_ptrace_core.c GUEST_SRCS-y := -GUEST_SRCS-y += xc_load_bin.c -GUEST_SRCS-y += xc_load_elf.c GUEST_SRCS-y += xg_private.c -#GUEST_SRCS-$(CONFIG_X86) += xc_linux_build.c -#GUEST_SRCS-$(CONFIG_IA64) += xc_linux_build.c GUEST_SRCS-$(CONFIG_MIGRATE) += xc_linux_restore.c xc_linux_save.c GUEST_SRCS-$(CONFIG_HVM) += xc_hvm_build.c xc_hvm_restore.c xc_hvm_save.c diff -r 04c23c1ef888 -r d907467f08cd tools/libxc/xc_dom.h --- a/tools/libxc/xc_dom.h Sun Feb 18 16:13:13 2007 -0700 +++ b/tools/libxc/xc_dom.h Tue Feb 20 12:58:22 2007 -0700 @@ -6,6 +6,8 @@ typedef uint64_t xen_vaddr_t; typedef uint64_t xen_paddr_t; + +#define PRIpfn PRI_xen_pfn struct xc_dom_seg { xen_vaddr_t vstart; diff -r 04c23c1ef888 -r d907467f08cd tools/libxc/xc_domain.c --- a/tools/libxc/xc_domain.c Sun Feb 18 16:13:13 2007 -0700 +++ b/tools/libxc/xc_domain.c Tue Feb 20 12:58:22 2007 -0700 @@ -102,7 +102,7 @@ int xc_vcpu_setaffinity(int xc_handle, domctl.domain = (domid_t)domid; domctl.u.vcpuaffinity.vcpu = vcpu; - bitmap_64_to_byte(local, &cpumap, sizeof (cpumap)); + bitmap_64_to_byte(local, &cpumap, sizeof(cpumap) * 8); set_xen_guest_handle(domctl.u.vcpuaffinity.cpumap.bitmap, local); @@ -148,7 +148,7 @@ int xc_vcpu_getaffinity(int xc_handle, ret = do_domctl(xc_handle, &domctl); unlock_pages(local, sizeof (local)); - bitmap_byte_to_64(cpumap, local, sizeof (local)); + bitmap_byte_to_64(cpumap, local, sizeof(local) * 8); out: return ret; } diff -r 04c23c1ef888 -r d907467f08cd tools/libxc/xc_hvm_build.c --- a/tools/libxc/xc_hvm_build.c Sun Feb 18 16:13:13 2007 -0700 +++ b/tools/libxc/xc_hvm_build.c Tue Feb 20 12:58:22 2007 -0700 @@ -214,15 +214,6 @@ static int setup_guest(int xc_handle, v_start, v_end, elf_uval(&elf, elf.ehdr, e_entry)); - if ( (v_end - v_start) > ((unsigned long long)nr_pages << PAGE_SHIFT) ) - { - PERROR("Initial guest OS requires too much space: " - "(%lluMB is greater than %lluMB limit)\n", - (unsigned long long)(v_end - v_start) >> 20, - ((unsigned long long)nr_pages << PAGE_SHIFT) >> 20); - goto error_out; - } - if ( (page_array = malloc(nr_pages * sizeof(xen_pfn_t))) == NULL ) { PERROR("Could not allocate memory.\n"); diff -r 04c23c1ef888 -r d907467f08cd tools/libxc/xc_linux_build.c --- a/tools/libxc/xc_linux_build.c Sun Feb 18 16:13:13 2007 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1319 +0,0 @@ -/****************************************************************************** - * xc_linux_build.c - */ - -#include <stddef.h> -#include "xg_private.h" -#include "xc_private.h" -#include <xenctrl.h> - -#include "xc_elf.h" -#include <stdlib.h> -#include <unistd.h> -#include <inttypes.h> -#include <zlib.h> - -/* Handy for printing out '0' prepended values at native pointer size */ -#define _p(a) ((void *) ((ulong)a)) - -#define L1_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED) -#define L2_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER) -#if defined(__i386__) -#define L3_PROT (_PAGE_PRESENT) -#elif defined(__x86_64__) -#define L3_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER) -#define L4_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER) -#endif - -#define round_pgup(_p) (((_p)+(PAGE_SIZE-1))&PAGE_MASK) -#define round_pgdown(_p) ((_p)&PAGE_MASK) - -struct initrd_info { - enum { INITRD_none, INITRD_file, INITRD_mem } type; - /* - * .len must be filled in by the user for type==INITRD_mem. It is - * filled in by load_initrd() for INITRD_file and unused for - * INITRD_none. - */ - unsigned long len; - union { - gzFile file_handle; - char *mem_addr; - } u; -}; - -static const char *feature_names[XENFEAT_NR_SUBMAPS*32] = { - [XENFEAT_writable_page_tables] = "writable_page_tables", - [XENFEAT_writable_descriptor_tables] = "writable_descriptor_tables", - [XENFEAT_auto_translated_physmap] = "auto_translated_physmap", - [XENFEAT_supervisor_mode_kernel] = "supervisor_mode_kernel", - [XENFEAT_pae_pgdir_above_4gb] = "pae_pgdir_above_4gb" -}; - -static inline void set_feature_bit (int nr, uint32_t *addr) -{ - addr[nr>>5] |= (1<<(nr&31)); -} - -static inline int test_feature_bit(int nr, uint32_t *addr) -{ - return !!(addr[nr>>5] & (1<<(nr&31))); -} - -static int parse_features( - const char *feats, - uint32_t supported[XENFEAT_NR_SUBMAPS], - uint32_t required[XENFEAT_NR_SUBMAPS]) -{ - const char *end, *p; - int i, req; - - if ( (end = strchr(feats, ',')) == NULL ) - end = feats + strlen(feats); - - while ( feats < end ) - { - p = strchr(feats, '|'); - if ( (p == NULL) || (p > end) ) - p = end; - - req = (*feats == '!'); - if ( req ) - feats++; - - for ( i = 0; i < XENFEAT_NR_SUBMAPS*32; i++ ) - { - if ( feature_names[i] == NULL ) - continue; - - if ( strncmp(feature_names[i], feats, p-feats) == 0 ) - { - set_feature_bit(i, supported); - if ( required && req ) - set_feature_bit(i, required); - break; - } - } - - if ( i == XENFEAT_NR_SUBMAPS*32 ) - { - ERROR("Unknown feature \"%.*s\".", (int)(p-feats), feats); - if ( req ) - { - ERROR("Kernel requires an unknown hypervisor feature."); - return -EINVAL; - } - } - - feats = p; - if ( *feats == '|' ) - feats++; - } - - return -EINVAL; -} - -static int probeimageformat(const char *image, - unsigned long image_size, - struct load_funcs *load_funcs) -{ - if ( probe_elf(image, image_size, load_funcs) && - probe_bin(image, image_size, load_funcs) ) - { - xc_set_error(XC_INVALID_KERNEL, "Not a valid ELF or raw kernel image"); - return -EINVAL; - } - - return 0; -} - -static int load_initrd(int xc_handle, domid_t dom, - struct initrd_info *initrd, - unsigned long physbase, - xen_pfn_t *phys_to_mach) -{ - char page[PAGE_SIZE]; - unsigned long pfn_start, pfn; - - if ( initrd->type == INITRD_none ) - return 0; - - pfn_start = physbase >> PAGE_SHIFT; - - if ( initrd->type == INITRD_mem ) - { - unsigned long nr_pages = (initrd->len + PAGE_SIZE - 1) >> PAGE_SHIFT; - - for ( pfn = pfn_start; pfn < (pfn_start + nr_pages); pfn++ ) - { - xc_copy_to_domain_page( - xc_handle, dom, phys_to_mach[pfn], - &initrd->u.mem_addr[(pfn - pfn_start) << PAGE_SHIFT]); - } - } - else - { - int readlen; - - pfn = pfn_start; - initrd->len = 0; - - /* gzread returns 0 on EOF */ - while ( (readlen = gzread(initrd->u.file_handle, page, PAGE_SIZE)) ) - { - if ( readlen < 0 ) - { - PERROR("Error reading initrd image, could not"); - return -EINVAL; - } - - initrd->len += readlen; - xc_copy_to_domain_page(xc_handle, dom, phys_to_mach[pfn++], page); - } - } - - return 0; -} - -#define alloc_pt(ltab, vltab) \ -do { \ - ltab = ppt_alloc++; \ - ltab = (uint64_t)page_array[ltab] << PAGE_SHIFT; \ - if ( vltab != NULL ) \ - munmap(vltab, PAGE_SIZE); \ - if ( (vltab = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE, \ - PROT_READ|PROT_WRITE, \ - ltab >> PAGE_SHIFT)) == NULL ) \ - goto error_out; \ - memset(vltab, 0x0, PAGE_SIZE); \ -} while ( 0 ) - -#if defined(__i386__) - -static int setup_pg_tables(int xc_handle, uint32_t dom, - vcpu_guest_context_t *ctxt, - unsigned long dsi_v_start, - unsigned long v_end, - xen_pfn_t *page_array, - unsigned long vpt_start, - unsigned long vpt_end, - unsigned shadow_mode_enabled) -{ - l1_pgentry_t *vl1tab=NULL, *vl1e=NULL; - l2_pgentry_t *vl2tab=NULL, *vl2e=NULL; - unsigned long l1tab = 0; - unsigned long l2tab = 0; - unsigned long ppt_alloc; - unsigned long count; - - ppt_alloc = (vpt_start - dsi_v_start) >> PAGE_SHIFT; - alloc_pt(l2tab, vl2tab); - vl2e = &vl2tab[l2_table_offset(dsi_v_start)]; - ctxt->ctrlreg[3] = xen_pfn_to_cr3(l2tab >> PAGE_SHIFT); - - for ( count = 0; count < ((v_end - dsi_v_start) >> PAGE_SHIFT); count++ ) - { - if ( ((unsigned long)vl1e & (PAGE_SIZE-1)) == 0 ) - { - alloc_pt(l1tab, vl1tab); - vl1e = &vl1tab[l1_table_offset(dsi_v_start + (count<<PAGE_SHIFT))]; - *vl2e++ = l1tab | L2_PROT; - } - - *vl1e = (page_array[count] << PAGE_SHIFT) | L1_PROT; - - if ( !shadow_mode_enabled ) - if ( (count >= ((vpt_start-dsi_v_start)>>PAGE_SHIFT)) && - (count < ((vpt_end -dsi_v_start)>>PAGE_SHIFT)) ) - *vl1e &= ~_PAGE_RW; - - vl1e++; - } - munmap(vl1tab, PAGE_SIZE); - munmap(vl2tab, PAGE_SIZE); - return 0; - - error_out: - if (vl1tab) - munmap(vl1tab, PAGE_SIZE); - if (vl2tab) - munmap(vl2tab, PAGE_SIZE); - return -1; -} - -static int setup_pg_tables_pae(int xc_handle, uint32_t dom, - vcpu_guest_context_t *ctxt, - unsigned long dsi_v_start, - unsigned long v_end, - xen_pfn_t *page_array, - unsigned long vpt_start, - unsigned long vpt_end, - unsigned shadow_mode_enabled, - unsigned pae_mode) -{ - l1_pgentry_64_t *vl1tab = NULL, *vl1e = NULL; - l2_pgentry_64_t *vl2tab = NULL, *vl2e = NULL; - l3_pgentry_64_t *vl3tab = NULL, *vl3e = NULL; - uint64_t l1tab, l2tab, l3tab; - unsigned long ppt_alloc, count, nmfn; - - /* First allocate page for page dir. */ - ppt_alloc = (vpt_start - dsi_v_start) >> PAGE_SHIFT; - - if ( pae_mode == PAEKERN_extended_cr3 ) - { - ctxt->vm_assist |= (1UL << VMASST_TYPE_pae_extended_cr3); - } - else if ( page_array[ppt_alloc] > 0xfffff ) - { - nmfn = xc_make_page_below_4G(xc_handle, dom, page_array[ppt_alloc]); - if ( nmfn == 0 ) - { - DPRINTF("Couldn't get a page below 4GB :-(\n"); - goto error_out; - } - page_array[ppt_alloc] = nmfn; - } - - alloc_pt(l3tab, vl3tab); - vl3e = &vl3tab[l3_table_offset_pae(dsi_v_start)]; - ctxt->ctrlreg[3] = xen_pfn_to_cr3(l3tab >> PAGE_SHIFT); - - for ( count = 0; count < ((v_end - dsi_v_start) >> PAGE_SHIFT); count++) - { - if ( !((unsigned long)vl1e & (PAGE_SIZE-1)) ) - { - if ( !((unsigned long)vl2e & (PAGE_SIZE-1)) ) - { - alloc_pt(l2tab, vl2tab); - vl2e = &vl2tab[l2_table_offset_pae( - dsi_v_start + (count << PAGE_SHIFT))]; - *vl3e++ = l2tab | L3_PROT; - } - - alloc_pt(l1tab, vl1tab); - vl1e = &vl1tab[l1_table_offset_pae( - dsi_v_start + (count << PAGE_SHIFT))]; - *vl2e++ = l1tab | L2_PROT; - - } - - *vl1e = ((uint64_t)page_array[count] << PAGE_SHIFT) | L1_PROT; - - if ( !shadow_mode_enabled ) - if ( (count >= ((vpt_start-dsi_v_start)>>PAGE_SHIFT)) && - (count < ((vpt_end -dsi_v_start)>>PAGE_SHIFT)) ) - *vl1e &= ~_PAGE_RW; - - vl1e++; - } - - /* Xen requires a mid-level pgdir mapping 0xC0000000 region. */ - if ( (vl3tab[3] & _PAGE_PRESENT) == 0 ) - { - alloc_pt(l2tab, vl2tab); - vl3tab[3] = l2tab | L3_PROT; - } - - munmap(vl1tab, PAGE_SIZE); - munmap(vl2tab, PAGE_SIZE); - munmap(vl3tab, PAGE_SIZE); - return 0; - - error_out: - if (vl1tab) - munmap(vl1tab, PAGE_SIZE); - if (vl2tab) - munmap(vl2tab, PAGE_SIZE); - if (vl3tab) - munmap(vl3tab, PAGE_SIZE); - return -1; -} - -#endif - -#if defined(__x86_64__) - -static int setup_pg_tables_64(int xc_handle, uint32_t dom, - vcpu_guest_context_t *ctxt, - unsigned long dsi_v_start, - unsigned long v_end, - xen_pfn_t *page_array, - unsigned long vpt_start, - unsigned long vpt_end, - int shadow_mode_enabled) -{ - l1_pgentry_t *vl1tab=NULL, *vl1e=NULL; - l2_pgentry_t *vl2tab=NULL, *vl2e=NULL; - l3_pgentry_t *vl3tab=NULL, *vl3e=NULL; - l4_pgentry_t *vl4tab=NULL, *vl4e=NULL; - unsigned long l2tab = 0; - unsigned long l1tab = 0; - unsigned long l3tab = 0; - unsigned long l4tab = 0; - unsigned long ppt_alloc; - unsigned long count; - - /* First allocate page for page dir. */ - ppt_alloc = (vpt_start - dsi_v_start) >> PAGE_SHIFT; - alloc_pt(l4tab, vl4tab); - vl4e = &vl4tab[l4_table_offset(dsi_v_start)]; - ctxt->ctrlreg[3] = xen_pfn_to_cr3(l4tab >> PAGE_SHIFT); - - for ( count = 0; count < ((v_end-dsi_v_start)>>PAGE_SHIFT); count++) - { - if ( !((unsigned long)vl1e & (PAGE_SIZE-1)) ) - { - alloc_pt(l1tab, vl1tab); - - if ( !((unsigned long)vl2e & (PAGE_SIZE-1)) ) - { - alloc_pt(l2tab, vl2tab); - if ( !((unsigned long)vl3e & (PAGE_SIZE-1)) ) - { - alloc_pt(l3tab, vl3tab); - vl3e = &vl3tab[l3_table_offset(dsi_v_start + (count<<PAGE_SHIFT))]; - *vl4e++ = l3tab | L4_PROT; - } - vl2e = &vl2tab[l2_table_offset(dsi_v_start + (count<<PAGE_SHIFT))]; - *vl3e++ = l2tab | L3_PROT; - } - vl1e = &vl1tab[l1_table_offset(dsi_v_start + (count<<PAGE_SHIFT))]; - *vl2e++ = l1tab | L2_PROT; - } - - *vl1e = (page_array[count] << PAGE_SHIFT) | L1_PROT; - - if ( !shadow_mode_enabled ) - if ( (count >= ((vpt_start-dsi_v_start)>>PAGE_SHIFT)) && - (count < ((vpt_end -dsi_v_start)>>PAGE_SHIFT)) ) - *vl1e &= ~_PAGE_RW; - - vl1e++; - } - - munmap(vl1tab, PAGE_SIZE); - munmap(vl2tab, PAGE_SIZE); - munmap(vl3tab, PAGE_SIZE); - munmap(vl4tab, PAGE_SIZE); - return 0; - - error_out: - if (vl1tab) - munmap(vl1tab, PAGE_SIZE); - if (vl2tab) - munmap(vl2tab, PAGE_SIZE); - if (vl3tab) - munmap(vl3tab, PAGE_SIZE); - if (vl4tab) - munmap(vl4tab, PAGE_SIZE); - return -1; -} -#endif - -#ifdef __ia64__ -static int setup_guest(int xc_handle, - uint32_t dom, - const char *image, unsigned long image_size, - struct initrd_info *initrd, - unsigned long nr_pages, - unsigned long *pvsi, unsigned long *pvke, - unsigned long *pvss, vcpu_guest_context_t *ctxt, - const char *cmdline, - unsigned long shared_info_frame, - unsigned long flags, - unsigned int store_evtchn, unsigned long *store_mfn, - unsigned int console_evtchn, unsigned long *console_mfn, - uint32_t required_features[XENFEAT_NR_SUBMAPS]) -{ - xen_pfn_t *page_array = NULL; - struct load_funcs load_funcs; - struct domain_setup_info dsi; - unsigned long vinitrd_start; - unsigned long vinitrd_end; - unsigned long v_end; - unsigned long start_page, pgnr; - start_info_t *start_info; - unsigned long start_info_mpa; - struct xen_ia64_boot_param *bp; - shared_info_t *shared_info; - int i; - DECLARE_DOMCTL; - int rc; - - rc = probeimageformat(image, image_size, &load_funcs); - if ( rc != 0 ) - goto error_out; - - memset(&dsi, 0, sizeof(struct domain_setup_info)); - - rc = (load_funcs.parseimage)(image, image_size, &dsi); - if ( rc != 0 ) - goto error_out; - - if ( (page_array = malloc(nr_pages * sizeof(xen_pfn_t))) == NULL ) - { - PERROR("Could not allocate memory"); - goto error_out; - } - for ( i = 0; i < nr_pages; i++ ) - page_array[i] = i; - if ( xc_domain_memory_populate_physmap(xc_handle, dom, nr_pages, - 0, 0, page_array) ) - { - PERROR("Could not allocate memory for PV guest.\n"); - goto error_out; - } - - dsi.v_start = round_pgdown(dsi.v_start); - vinitrd_start = round_pgup(dsi.v_end); - start_info_mpa = (nr_pages - 3) << PAGE_SHIFT; - *pvke = dsi.v_kernentry; - - /* Build firmware. */ - memset(&domctl.u.arch_setup, 0, sizeof(domctl.u.arch_setup)); - domctl.u.arch_setup.flags = 0; - domctl.u.arch_setup.bp = start_info_mpa + sizeof (start_info_t); - domctl.u.arch_setup.maxmem = (nr_pages - 3) << PAGE_SHIFT; - domctl.cmd = XEN_DOMCTL_arch_setup; - domctl.domain = (domid_t)dom; - if ( xc_domctl(xc_handle, &domctl) ) - goto error_out; - - start_page = dsi.v_start >> PAGE_SHIFT; - /* in order to get initrd->len, we need to load initrd image at first */ - if ( load_initrd(xc_handle, dom, initrd, - vinitrd_start - dsi.v_start, page_array + start_page) ) - goto error_out; - - vinitrd_end = vinitrd_start + initrd->len; - v_end = round_pgup(vinitrd_end); - pgnr = (v_end - dsi.v_start) >> PAGE_SHIFT; - if ( pgnr > nr_pages ) - { - PERROR("too small memory is specified. " - "At least %ld kb is necessary.\n", - pgnr << (PAGE_SHIFT - 10)); - } - - IPRINTF("VIRTUAL MEMORY ARRANGEMENT:\n" - " Loaded kernel: %p->%p\n" - " Init. ramdisk: %p->%p\n" - " TOTAL: %p->%p\n", - _p(dsi.v_kernstart), _p(dsi.v_kernend), - _p(vinitrd_start), _p(vinitrd_end), - _p(dsi.v_start), _p(v_end)); - IPRINTF(" ENTRY ADDRESS: %p\n", _p(dsi.v_kernentry)); - - (load_funcs.loadimage)(image, image_size, xc_handle, dom, - page_array + start_page, &dsi); - - *store_mfn = page_array[nr_pages - 2]; //XXX - *console_mfn = page_array[nr_pages - 1]; //XXX - IPRINTF("start_info: 0x%lx at 0x%lx, " - "store_mfn: 0x%lx at 0x%lx, " - "console_mfn: 0x%lx at 0x%lx\n", - page_array[nr_pages - 3], nr_pages - 3, - *store_mfn, nr_pages - 2, - *console_mfn, nr_pages - 1); - - start_info = xc_map_foreign_range( - xc_handle, dom, PAGE_SIZE, PROT_READ|PROT_WRITE, - page_array[nr_pages - 3]); - if ( start_info == NULL ) - goto error_out; - - memset(start_info, 0, sizeof(*start_info)); - rc = xc_version(xc_handle, XENVER_version, NULL); - sprintf(start_info->magic, "xen-%i.%i-ia64", rc >> 16, rc & (0xFFFF)); - start_info->flags = flags; - start_info->store_mfn = nr_pages - 2; - start_info->store_evtchn = store_evtchn; - start_info->console.domU.mfn = nr_pages - 1; - start_info->console.domU.evtchn = console_evtchn; - start_info->nr_pages = nr_pages; // FIXME?: nr_pages - 2 ???? - - bp = (struct xen_ia64_boot_param *)(start_info + 1); - bp->command_line = start_info_mpa + offsetof(start_info_t, cmd_line); - if ( cmdline != NULL ) - { - strncpy((char *)start_info->cmd_line, cmdline, MAX_GUEST_CMDLINE); - start_info->cmd_line[MAX_GUEST_CMDLINE - 1] = 0; - } - if ( initrd->len != 0 ) - { - bp->initrd_start = vinitrd_start; - bp->initrd_size = initrd->len; - } - ctxt->user_regs.r28 = start_info_mpa + sizeof (start_info_t); - munmap(start_info, PAGE_SIZE); - - /* - * shared_info is assiged into guest pseudo physical address space - * by XEN_DOMCTL_arch_setup. shared_info_frame is stale value until that. - * So passed shared_info_frame is stale. obtain the right value here. - */ - domctl.cmd = XEN_DOMCTL_getdomaininfo; - domctl.domain = (domid_t)dom; - if ( (xc_domctl(xc_handle, &domctl) < 0) || - ((uint16_t)domctl.domain != dom) ) - { - PERROR("Could not get info on domain"); - goto error_out; - } - shared_info_frame = domctl.u.getdomaininfo.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); - printf("shared_info = %p frame=%lx\n", - shared_info, shared_info_frame); - //memset(shared_info, 0, PAGE_SIZE); - /* Mask all upcalls... */ - for ( i = 0; i < MAX_VIRT_CPUS; i++ ) - shared_info->vcpu_info[i].evtchn_upcall_mask = 1; - shared_info->arch.start_info_pfn = nr_pages - 3; - - munmap(shared_info, PAGE_SIZE); - free(page_array); - return 0; - - error_out: - free(page_array); - return -1; -} -#else /* x86 */ - -/* Check if the platform supports the guest kernel format */ -static int compat_check(int xc_handle, struct domain_setup_info *dsi) -{ - xen_capabilities_info_t xen_caps = ""; - - if (xc_version(xc_handle, XENVER_capabilities, &xen_caps) != 0) { - xc_set_error(XC_INVALID_KERNEL, - "Cannot determine host capabilities."); - return 0; - } - -#ifndef __x86_64__//temp - if (strstr(xen_caps, "xen-3.0-x86_32p")) { - if (dsi->pae_kernel == PAEKERN_bimodal) { - dsi->pae_kernel = PAEKERN_extended_cr3; - } else if (dsi->pae_kernel == PAEKERN_no) { - xc_set_error(XC_INVALID_KERNEL, - "Non PAE-kernel on PAE host."); - return 0; - } - } else { - if (dsi->pae_kernel == PAEKERN_bimodal) { - dsi->pae_kernel = PAEKERN_no; - } else if (dsi->pae_kernel != PAEKERN_no) { - xc_set_error(XC_INVALID_KERNEL, - "PAE-kernel on non-PAE host."); - return 0; - } - } -#endif - - return 1; -} - -static inline int increment_ulong(unsigned long *pval, unsigned long inc) -{ - if ( inc >= -*pval ) - { - ERROR("Value wrapped to zero: image too large?"); - return 0; - } - *pval += inc; - return 1; -} - -static int setup_guest(int xc_handle, - uint32_t dom, - const char *image, unsigned long image_size, - struct initrd_info *initrd, - unsigned long nr_pages, - unsigned long *pvsi, unsigned long *pvke, - unsigned long *pvss, vcpu_guest_context_t *ctxt, - const char *cmdline, - unsigned long shared_info_frame, - unsigned long flags, - unsigned int store_evtchn, unsigned long *store_mfn, - unsigned int console_evtchn, unsigned long *console_mfn, - uint32_t required_features[XENFEAT_NR_SUBMAPS]) -{ - xen_pfn_t *page_array = NULL; - unsigned long count, i; - unsigned long long hypercall_page; - int hypercall_page_defined; - start_info_t *start_info; - shared_info_t *shared_info; - const char *p; - DECLARE_DOMCTL; - int rc; - - unsigned long nr_pt_pages; - unsigned long physmap_pfn; - xen_pfn_t *physmap, *physmap_e; - - struct load_funcs load_funcs; - struct domain_setup_info dsi; - unsigned long vinitrd_start; - unsigned long vphysmap_start; - unsigned long vstartinfo_start; - unsigned long vstoreinfo_start; - unsigned long vconsole_start; - unsigned long vsharedinfo_start = 0; /* XXX gcc */ - unsigned long vstack_start; - unsigned long vstack_end; - unsigned long vpt_start; - unsigned long vpt_end; - unsigned long v_end; - unsigned long guest_store_mfn, guest_console_mfn, guest_shared_info_mfn; - unsigned long shadow_mode_enabled; - uint32_t supported_features[XENFEAT_NR_SUBMAPS] = { 0, }; - - rc = probeimageformat(image, image_size, &load_funcs); - if ( rc != 0 ) - goto error_out; - - memset(&dsi, 0, sizeof(struct domain_setup_info)); - - rc = (load_funcs.parseimage)(image, image_size, &dsi); - if ( rc != 0 ) - goto error_out; - - if ( (dsi.v_start & (PAGE_SIZE-1)) != 0 ) - { - PERROR("Guest OS must load to a page boundary."); - goto error_out; - } - - if ( !compat_check(xc_handle, &dsi) ) - goto error_out; - - /* Parse and validate kernel features. */ - if ( (p = xen_elfnote_string(&dsi, XEN_ELFNOTE_FEATURES)) != NULL ) - { - if ( !parse_features(p, supported_features, required_features) ) - { - ERROR("Failed to parse guest kernel features."); - goto error_out; - } - - IPRINTF("Supported features = { %08x }.\n", supported_features[0]); - IPRINTF("Required features = { %08x }.\n", required_features[0]); - } - - for ( i = 0; i < XENFEAT_NR_SUBMAPS; i++ ) - { - if ( (supported_features[i] & required_features[i]) != - required_features[i] ) - { - ERROR("Guest kernel does not support a required feature."); - goto error_out; - } - } - - shadow_mode_enabled = test_feature_bit(XENFEAT_auto_translated_physmap, - required_features); - - if ( (page_array = malloc(nr_pages * sizeof(unsigned long))) == NULL ) - { - PERROR("Could not allocate memory"); - goto error_out; - } - - for ( i = 0; i < nr_pages; i++ ) - page_array[i] = i; - - if ( xc_domain_memory_populate_physmap(xc_handle, dom, nr_pages, - 0, 0, page_array) ) - { - PERROR("Could not allocate memory for PV guest.\n"); - goto error_out; - } - - - if ( shadow_mode_enabled ) - { - /* - * Enable shadow translate mode. This must happen after - * populate physmap because the p2m reservation is based on - * the domain's current memory allocation. - */ - if ( xc_shadow_control(xc_handle, dom, - XEN_DOMCTL_SHADOW_OP_ENABLE_TRANSLATE, - NULL, 0, NULL, 0, NULL) < 0 ) - { - PERROR("Could not enable translation mode"); - goto error_out; - } - - /* Reinitialise the gpfn->gmfn array. */ - for ( i = 0; i < nr_pages; i++ ) - page_array[i] = i; - } - - rc = (load_funcs.loadimage)(image, image_size, - xc_handle, dom, page_array, - &dsi); - if ( rc != 0 ) - goto error_out; - - /* - * Why do we need this? The number of page-table frames depends on the - * size of the bootstrap address space. But the size of the address space - * depends on the number of page-table frames (since each one is mapped - * read-only). We have a pair of simultaneous equations in two unknowns, - * which we solve by exhaustive search. - */ - v_end = round_pgup(dsi.v_end); - if ( v_end == 0 ) - { - ERROR("End of mapped kernel image too close to end of memory"); - goto error_out; - } - - vinitrd_start = v_end; - if ( load_initrd(xc_handle, dom, initrd, - vinitrd_start - dsi.v_start, page_array) ) - goto error_out; - if ( !increment_ulong(&v_end, round_pgup(initrd->len)) ) - goto error_out; - - vphysmap_start = v_end; - if ( !increment_ulong(&v_end, round_pgup(nr_pages * sizeof(long))) ) - goto error_out; - vstartinfo_start = v_end; - if ( !increment_ulong(&v_end, PAGE_SIZE) ) - goto error_out; - vstoreinfo_start = v_end; - if ( !increment_ulong(&v_end, PAGE_SIZE) ) - goto error_out; - vconsole_start = v_end; - if ( !increment_ulong(&v_end, PAGE_SIZE) ) - goto error_out; - if ( shadow_mode_enabled ) { - vsharedinfo_start = v_end; - if ( !increment_ulong(&v_end, PAGE_SIZE) ) - goto error_out; - } - vpt_start = v_end; - - for ( nr_pt_pages = 2; ; nr_pt_pages++ ) - { - /* vpt_end = vpt_staret + (nr_pt_pages * PAGE_SIZE); */ - vpt_end = vpt_start; - if ( !increment_ulong(&vpt_end, nr_pt_pages * PAGE_SIZE) ) - goto error_out; - - vstack_start = vpt_end; - /* vstack_end = vstack_start + PAGE_SIZE; */ - vstack_end = vstack_start; - if ( !increment_ulong(&vstack_end, PAGE_SIZE) ) - goto error_out; - - /* v_end = (vstack_end + (1UL<<22)-1) & ~((1UL<<22)-1); */ - v_end = vstack_end; - if ( !increment_ulong(&v_end, (1UL<<22)-1) ) - goto error_out; - v_end &= ~((1UL<<22)-1); - - if ( (v_end - vstack_end) < (512UL << 10) ) - { - /* Add extra 4MB to get >= 512kB padding. */ - if ( !increment_ulong(&v_end, 1UL << 22) ) - goto error_out; - } - -#define NR(_l,_h,_s) \ - (((((unsigned long)(_h) + ((1UL<<(_s))-1)) & ~((1UL<<(_s))-1)) - \ - ((unsigned long)(_l) & ~((1UL<<(_s))-1))) >> (_s)) -#if defined(__i386__) - if ( dsi.pae_kernel != PAEKERN_no ) - { - if ( (1 + /* # L3 */ - NR(dsi.v_start, v_end, L3_PAGETABLE_SHIFT_PAE) + /* # L2 */ - NR(dsi.v_start, v_end, L2_PAGETABLE_SHIFT_PAE) + /* # L1 */ - /* Include a fourth mid-level page directory for Xen. */ - (v_end <= (3 << L3_PAGETABLE_SHIFT_PAE))) - <= nr_pt_pages ) - break; - } - else - { - if ( (1 + /* # L2 */ - NR(dsi.v_start, v_end, L2_PAGETABLE_SHIFT)) /* # L1 */ - <= nr_pt_pages ) - break; - } -#elif defined(__x86_64__) - if ( (1 + /* # L4 */ - NR(dsi.v_start, v_end, L4_PAGETABLE_SHIFT) + /* # L3 */ - NR(dsi.v_start, v_end, L3_PAGETABLE_SHIFT) + /* # L2 */ - NR(dsi.v_start, v_end, L2_PAGETABLE_SHIFT)) /* # L1 */ - <= nr_pt_pages ) - break; -#endif - } - - IPRINTF("VIRTUAL MEMORY ARRANGEMENT:\n"); - IPRINTF(" Loaded kernel: %p->%p\n", _p(dsi.v_kernstart), - _p(dsi.v_kernend)); - if ( initrd->len ) - IPRINTF(" Initial ramdisk: %p->%p\n", _p(vinitrd_start), - _p(vinitrd_start + initrd->len)); - IPRINTF(" Phys-Mach map: %p\n", _p(vphysmap_start)); - IPRINTF(" Start info: %p\n", _p(vstartinfo_start)); - IPRINTF(" Store page: %p\n", _p(vstoreinfo_start)); - IPRINTF(" Console page: %p\n", _p(vconsole_start)); - if ( shadow_mode_enabled ) - IPRINTF(" Shared Info page: %p\n", _p(vsharedinfo_start)); - IPRINTF(" Page tables: %p\n", _p(vpt_start)); - IPRINTF(" Boot stack: %p\n", _p(vstack_start)); - IPRINTF(" TOTAL: %p->%p\n", _p(dsi.v_start), _p(v_end)); - IPRINTF(" ENTRY ADDRESS: %p\n", _p(dsi.v_kernentry)); - - if ( ((v_end - dsi.v_start)>>PAGE_SHIFT) > nr_pages ) - { - PERROR("Initial guest OS requires too much space\n" - "(%pMB is greater than %luMB limit)\n", - _p((v_end-dsi.v_start)>>20), nr_pages>>(20-PAGE_SHIFT)); - goto error_out; - } - -#if defined(__i386__) - if ( dsi.pae_kernel != PAEKERN_no ) - rc = setup_pg_tables_pae(xc_handle, dom, ctxt, - dsi.v_start, v_end, - page_array, vpt_start, vpt_end, - shadow_mode_enabled, dsi.pae_kernel); - else - rc = setup_pg_tables(xc_handle, dom, ctxt, - dsi.v_start, v_end, - page_array, vpt_start, vpt_end, - shadow_mode_enabled); -#endif -#if defined(__x86_64__) - rc = setup_pg_tables_64(xc_handle, dom, ctxt, - dsi.v_start, v_end, - page_array, vpt_start, vpt_end, - shadow_mode_enabled); -#endif - if ( rc != 0 ) - goto error_out; - - /* - * Pin down l2tab addr as page dir page - causes hypervisor to provide - * correct protection for the page - */ - if ( !shadow_mode_enabled ) - { -#if defined(__i386__) - if ( dsi.pae_kernel != PAEKERN_no ) - { - if ( pin_table(xc_handle, MMUEXT_PIN_L3_TABLE, - xen_cr3_to_pfn(ctxt->ctrlreg[3]), dom) ) - goto error_out; - } - else - { - if ( pin_table(xc_handle, MMUEXT_PIN_L2_TABLE, - xen_cr3_to_pfn(ctxt->ctrlreg[3]), dom) ) - goto error_out; - } -#elif defined(__x86_64__) - /* - * Pin down l4tab addr as page dir page - causes hypervisor to provide - * correct protection for the page - */ - if ( pin_table(xc_handle, MMUEXT_PIN_L4_TABLE, - xen_cr3_to_pfn(ctxt->ctrlreg[3]), dom) ) - goto error_out; -#endif - } - - /* Write the phys->machine table entries (machine->phys already done). */ - physmap_pfn = (vphysmap_start - dsi.v_start) >> PAGE_SHIFT; - physmap = physmap_e = xc_map_foreign_range( - xc_handle, dom, PAGE_SIZE, PROT_READ|PROT_WRITE, - page_array[physmap_pfn++]); - for ( count = 0; count < nr_pages; count++ ) - { - *physmap_e++ = page_array[count]; - if ( ((unsigned long)physmap_e & (PAGE_SIZE-1)) == 0 ) - { - munmap(physmap, PAGE_SIZE); - physmap = physmap_e = xc_map_foreign_range( - xc_handle, dom, PAGE_SIZE, PROT_READ|PROT_WRITE, - page_array[physmap_pfn++]); - } - } - munmap(physmap, PAGE_SIZE); - - if ( shadow_mode_enabled ) - { - struct xen_add_to_physmap xatp; - - guest_shared_info_mfn = (vsharedinfo_start-dsi.v_start) >> PAGE_SHIFT; - - /* Map shared info frame into guest physmap. */ - xatp.domid = dom; - xatp.space = XENMAPSPACE_shared_info; - xatp.idx = 0; - xatp.gpfn = guest_shared_info_mfn; - rc = xc_memory_op(xc_handle, XENMEM_add_to_physmap, &xatp); - if ( rc != 0 ) - { - PERROR("Cannot map shared info pfn"); - goto error_out; - } - - /* Map grant table frames into guest physmap. */ - for ( i = 0; ; i++ ) - { - xatp.domid = dom; - xatp.space = XENMAPSPACE_grant_table; - xatp.idx = i; - xatp.gpfn = nr_pages + i; - rc = xc_memory_op(xc_handle, XENMEM_add_to_physmap, &xatp); - if ( rc != 0 ) - { - if ( errno == EINVAL ) - break; /* done all grant tables */ - PERROR("Cannot map grant table pfn"); - goto error_out; - } - } - } - else - { - guest_shared_info_mfn = shared_info_frame; - } - - *store_mfn = page_array[(vstoreinfo_start-dsi.v_start) >> PAGE_SHIFT]; - *console_mfn = page_array[(vconsole_start-dsi.v_start) >> PAGE_SHIFT]; - if ( xc_clear_domain_page(xc_handle, dom, *store_mfn) || - xc_clear_domain_page(xc_handle, dom, *console_mfn) ) - goto error_out; - if ( shadow_mode_enabled ) - { - guest_store_mfn = (vstoreinfo_start-dsi.v_start) >> PAGE_SHIFT; - guest_console_mfn = (vconsole_start-dsi.v_start) >> PAGE_SHIFT; - } - else - { - guest_store_mfn = *store_mfn; - guest_console_mfn = *console_mfn; - } - - start_info = xc_map_foreign_range( - xc_handle, dom, PAGE_SIZE, PROT_READ|PROT_WRITE, - page_array[(vstartinfo_start-dsi.v_start)>>PAGE_SHIFT]); - /*shared_info, start_info */ - memset(start_info, 0, sizeof(*start_info)); - rc = xc_version(xc_handle, XENVER_version, NULL); - sprintf(start_info->magic, "xen-%i.%i-x86_%d%s", - rc >> 16, rc & (0xFFFF), (unsigned int)sizeof(long)*8, - (dsi.pae_kernel != PAEKERN_no) ? "p" : ""); - start_info->nr_pages = nr_pages; - start_info->shared_info = guest_shared_info_mfn << PAGE_SHIFT; - start_info->flags = flags; - start_info->pt_base = vpt_start; - start_info->nr_pt_frames = nr_pt_pages; - start_info->mfn_list = vphysmap_start; - start_info->store_mfn = guest_store_mfn; - start_info->store_evtchn = store_evtchn; - start_info->console.domU.mfn = guest_console_mfn; - start_info->console.domU.evtchn = console_evtchn; - if ( initrd->len != 0 ) - { - start_info->mod_start = vinitrd_start; - start_info->mod_len = initrd->len; - } - if ( cmdline != NULL ) - { - strncpy((char *)start_info->cmd_line, cmdline, MAX_GUEST_CMDLINE); - start_info->cmd_line[MAX_GUEST_CMDLINE-1] = '\0'; - } - munmap(start_info, PAGE_SIZE); - - /* 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... */ - for ( i = 0; i < MAX_VIRT_CPUS; i++ ) - shared_info->vcpu_info[i].evtchn_upcall_mask = 1; - - munmap(shared_info, PAGE_SIZE); - - hypercall_page = xen_elfnote_numeric(&dsi, XEN_ELFNOTE_HYPERCALL_PAGE, - &hypercall_page_defined); - if ( hypercall_page_defined ) - { - unsigned long long pfn = (hypercall_page - dsi.v_start) >> PAGE_SHIFT; - if ( pfn >= nr_pages ) - goto error_out; - domctl.domain = (domid_t)dom; - domctl.u.hypercall_init.gmfn = page_array[pfn]; - domctl.cmd = XEN_DOMCTL_hypercall_init; - if ( xc_domctl(xc_handle, &domctl) ) - goto error_out; - } - - free(page_array); - - *pvsi = vstartinfo_start; - *pvss = vstack_start; - *pvke = dsi.v_kernentry; - - return 0; - - error_out: - free(page_array); - return -1; -} -#endif - -static int xc_linux_build_internal(int xc_handle, - uint32_t domid, - unsigned int mem_mb, - const char *image, - unsigned long image_size, - struct initrd_info *initrd, - const char *cmdline, - const char *features, - unsigned long flags, - unsigned int store_evtchn, - unsigned long *store_mfn, - unsigned int console_evtchn, - unsigned long *console_mfn) -{ - struct xen_domctl launch_domctl; - DECLARE_DOMCTL; - int rc; - struct vcpu_guest_context st_ctxt, *ctxt = &st_ctxt; - unsigned long vstartinfo_start, vkern_entry, vstack_start; - uint32_t features_bitmap[XENFEAT_NR_SUBMAPS] = { 0, }; - - if ( features != NULL ) - { - if ( !parse_features(features, features_bitmap, NULL) ) - { - PERROR("Failed to parse configured features\n"); - goto error_out; - } - } - - memset(ctxt, 0, sizeof(*ctxt)); - - if ( lock_pages(ctxt, sizeof(*ctxt) ) ) - { - PERROR("%s: ctxt lock failed", __func__); - return 1; - } - - domctl.cmd = XEN_DOMCTL_getdomaininfo; - domctl.domain = (domid_t)domid; - if ( (xc_domctl(xc_handle, &domctl) < 0) || - ((uint16_t)domctl.domain != domid) ) - { - PERROR("Could not get info on domain"); - goto error_out; - } - - if ( setup_guest(xc_handle, domid, image, image_size, - initrd, - mem_mb << (20 - PAGE_SHIFT), - &vstartinfo_start, &vkern_entry, - &vstack_start, ctxt, cmdline, - domctl.u.getdomaininfo.shared_info_frame, - flags, store_evtchn, store_mfn, - console_evtchn, console_mfn, - features_bitmap) < 0 ) - { - goto error_out; - } - -#ifdef __ia64__ - /* based on new_thread in xen/arch/ia64/domain.c */ - ctxt->user_regs.cr_iip = vkern_entry; - ctxt->user_regs.cr_ifs = 1UL << 63; - ctxt->user_regs.ar_fpsr = xc_ia64_fpsr_default(); -#else /* x86 */ - /* - * Initial register values: - * DS,ES,FS,GS = FLAT_KERNEL_DS - * CS:EIP = FLAT_KERNEL_CS:start_pc - * SS:ESP = FLAT_KERNEL_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->user_regs.ds = FLAT_KERNEL_DS; - ctxt->user_regs.es = FLAT_KERNEL_DS; - ctxt->user_regs.fs = FLAT_KERNEL_DS; - ctxt->user_regs.gs = FLAT_KERNEL_DS; - ctxt->user_regs.ss = FLAT_KERNEL_SS; - ctxt->user_regs.cs = FLAT_KERNEL_CS; - ctxt->user_regs.eip = vkern_entry; - ctxt->user_regs.esp = vstack_start + PAGE_SIZE; - ctxt->user_regs.esi = vstartinfo_start; - ctxt->user_regs.eflags = 1 << 9; /* Interrupt Enable */ - - ctxt->flags = VGCF_IN_KERNEL; - - ctxt->kernel_ss = ctxt->user_regs.ss; - ctxt->kernel_sp = ctxt->user_regs.esp; -#endif /* x86 */ - - memset(&launch_domctl, 0, sizeof(launch_domctl)); - - launch_domctl.domain = (domid_t)domid; - launch_domctl.u.vcpucontext.vcpu = 0; - set_xen_guest_handle(launch_domctl.u.vcpucontext.ctxt, ctxt); - - launch_domctl.cmd = XEN_DOMCTL_setvcpucontext; - rc = xc_domctl(xc_handle, &launch_domctl); - - return rc; - - error_out: - return -1; -} - -int xc_linux_build_mem(int xc_handle, - uint32_t domid, - unsigned int mem_mb, - const char *image_buffer, - unsigned long image_size, - const char *initrd, - unsigned long initrd_len, - const char *cmdline, - const char *features, - unsigned long flags, - unsigned int store_evtchn, - unsigned long *store_mfn, - unsigned int console_evtchn, - unsigned long *console_mfn) -{ - int sts; - char *img_buf; - unsigned long img_len; - struct initrd_info initrd_info = { .type = INITRD_none }; - - /* A kernel buffer is required */ - if ( (image_buffer == NULL) || (image_size == 0) ) - { - ERROR("kernel image buffer not present"); - return -1; - } - - /* If it's gzipped, inflate it; otherwise, use as is */ - /* xc_inflate_buffer may return the same buffer pointer if */ - /* the buffer is already inflated */ - img_buf = xc_inflate_buffer(image_buffer, image_size, &img_len); - if ( img_buf == NULL ) - { - ERROR("unable to inflate kernel image buffer"); - return -1; - } - - /* RAM disks are optional; if we get one, inflate it */ - if ( initrd != NULL ) - { - initrd_info.type = INITRD_mem; - initrd_info.u.mem_addr = xc_inflate_buffer( - initrd, initrd_len, &initrd_info.len); - if ( initrd_info.u.mem_addr == NULL ) - { - ERROR("unable to inflate ram disk buffer"); - sts = -1; - goto out; - } - } - - sts = xc_linux_build_internal(xc_handle, domid, mem_mb, img_buf, img_len, - &initrd_info, cmdline, features, flags, - store_evtchn, store_mfn, - console_evtchn, console_mfn); - - out: - /* The inflation routines may pass back the same buffer so be */ - /* sure that we have a buffer and that it's not the one passed in. */ - /* Don't unnecessarily annoy/surprise/confound the caller */ - if ( (img_buf != NULL) && (img_buf != image_buffer) ) - free(img_buf); - if ( (initrd_info.u.mem_addr != NULL) && - (initrd_info.u.mem_addr != initrd) ) - free(initrd_info.u.mem_addr); - - return sts; -} - -int xc_linux_build(int xc_handle, - uint32_t domid, - unsigned int mem_mb, - const char *image_name, - const char *initrd_name, - const char *cmdline, - const char *features, - unsigned long flags, - unsigned int store_evtchn, - unsigned long *store_mfn, - unsigned int console_evtchn, - unsigned long *console_mfn) -{ - char *image = NULL; - unsigned long image_size; - struct initrd_info initrd_info = { .type = INITRD_none }; - int fd = -1, sts = -1; - - if ( (image_name == NULL) || - ((image = xc_read_image(image_name, &image_size)) == NULL )) - return -1; - - if ( (initrd_name != NULL) && (strlen(initrd_name) != 0) ) - { - initrd_info.type = INITRD_file; - - if ( (fd = open(initrd_name, O_RDONLY)) < 0 ) - { - PERROR("Could not open the initial ramdisk image"); - goto error_out; - } - - if ( (initrd_info.u.file_handle = gzdopen(fd, "rb")) == NULL ) - { - PERROR("Could not allocate decompression state for initrd"); - goto error_out; - } - } - - sts = xc_linux_build_internal(xc_handle, domid, mem_mb, image, image_size, - &initrd_info, cmdline, features, flags, - store_evtchn, store_mfn, - console_evtchn, console_mfn); - - error_out: - free(image); - if ( initrd_info.type == INITRD_file && initrd_info.u.file_handle ) - gzclose(initrd_info.u.file_handle); - else if ( fd >= 0 ) - close(fd); - - return sts; -} - -/* - * Local variables: - * mode: C - * c-set-style: "BSD" - * c-basic-offset: 4 - * tab-width: 4 - * indent-tabs-mode: nil - * End: - */ diff -r 04c23c1ef888 -r d907467f08cd tools/libxc/xc_linux_restore.c --- a/tools/libxc/xc_linux_restore.c Sun Feb 18 16:13:13 2007 -0700 +++ b/tools/libxc/xc_linux_restore.c Tue Feb 20 12:58:22 2007 -0700 @@ -82,7 +82,7 @@ static int uncanonicalize_pagetable(int if(!(pte & _PAGE_PRESENT)) continue; - pfn = (pte >> PAGE_SHIFT) & 0xffffffff; + pfn = (pte >> PAGE_SHIFT) & MFN_MASK_X86; if(pfn >= max_pfn) { /* This "page table page" is probably not one; bail. */ @@ -120,12 +120,12 @@ static int uncanonicalize_pagetable(int if(!(pte & _PAGE_PRESENT)) continue; - pfn = (pte >> PAGE_SHIFT) & 0xffffffff; + pfn = (pte >> PAGE_SHIFT) & MFN_MASK_X86; if(p2m[pfn] == INVALID_P2M_ENTRY) p2m[pfn] = p2m_batch[nr_mfns++]; - pte &= 0xffffff0000000fffULL; + pte &= ~MADDR_MASK_X86; pte |= (uint64_t)p2m[pfn] << PAGE_SHIFT; if(pt_levels == 2) diff -r 04c23c1ef888 -r d907467f08cd tools/libxc/xc_linux_save.c --- a/tools/libxc/xc_linux_save.c Sun Feb 18 16:13:13 2007 -0700 +++ b/tools/libxc/xc_linux_save.c Tue Feb 20 12:58:22 2007 -0700 @@ -495,7 +495,7 @@ static int canonicalize_pagetable(unsign hstart = (hvirt_start >> L2_PAGETABLE_SHIFT_PAE) & 0x1ff; he = ((const uint64_t *) spage)[hstart]; - if ( ((he >> PAGE_SHIFT) & 0x0fffffff) == m2p_mfn0 ) { + if ( ((he >> PAGE_SHIFT) & MFN_MASK_X86) == m2p_mfn0 ) { /* hvirt starts with xen stuff... */ xen_start = hstart; } else if ( hvirt_start != 0xf5800000 ) { @@ -503,7 +503,7 @@ static int canonicalize_pagetable(unsign hstart = (0xf5800000 >> L2_PAGETABLE_SHIFT_PAE) & 0x1ff; he = ((const uint64_t *) spage)[hstart]; - if( ((he >> PAGE_SHIFT) & 0x0fffffff) == m2p_mfn0 ) + if( ((he >> PAGE_SHIFT) & MFN_MASK_X86) == m2p_mfn0 ) xen_start = hstart; } } @@ -532,7 +532,7 @@ static int canonicalize_pagetable(unsign if (pte & _PAGE_PRESENT) { - mfn = (pte >> PAGE_SHIFT) & 0xfffffff; + mfn = (pte >> PAGE_SHIFT) & MFN_MASK_X86; if (!MFN_IS_IN_PSEUDOPHYS_MAP(mfn)) { /* This will happen if the type info is stale which is quite feasible under live migration */ @@ -541,7 +541,7 @@ static int canonicalize_pagetable(unsign } else pfn = mfn_to_pfn(mfn); - pte &= 0xffffff0000000fffULL; + pte &= ~MADDR_MASK_X86; pte |= (uint64_t)pfn << PAGE_SHIFT; } diff -r 04c23c1ef888 -r d907467f08cd tools/libxc/xc_load_bin.c --- a/tools/libxc/xc_load_bin.c Sun Feb 18 16:13:13 2007 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,306 +0,0 @@ -/****************************************************************************** - * xc_bin_load.c - * - * Based on xc_elf_load.c - * - * Loads simple binary images. It's like a .COM file in MS-DOS. No headers are - * present. The only requirement is that it must have a xen_bin_image table - * somewhere in the first 8192 bytes, starting on a 32-bit aligned address. - * Those familiar with the multiboot specification should recognize this, it's - * (almost) the same as the multiboot header. - * The layout of the xen_bin_image table is: - * - * Offset Type Name Note - * 0 uint32_t magic required - * 4 uint32_t flags required - * 8 uint32_t checksum required - * 12 uint32_t header_addr required - * 16 uint32_t load_addr required - * 20 uint32_t load_end_addr required - * 24 uint32_t bss_end_addr required - * 28 uint32_t entry_addr required - * - * - magic - * Magic number identifying the table. For images to be loaded by Xen 3, the - * magic value is 0x336ec578 ("xEn3" with the 0x80 bit of the "E" set). - * - flags - * bit 0: indicates whether the image needs to be loaded on a page boundary - * bit 1: reserved, must be 0 (the multiboot spec uses this bit to indicate - * that memory info should be passed to the image) - * bit 2: reserved, must be 0 (the multiboot spec uses this bit to indicate - * that the bootloader should pass video mode info to the image) - * bit 16: reserved, must be 1 (the multiboot spec uses this bit to indicate - * that the values in the fields header_addr - entry_addr are - * valid) - * All other bits should be set to 0. - * - checksum - * When added to "magic" and "flags", the resulting value should be 0. - * - header_addr - * Contains the virtual address corresponding to the beginning of the - * table - the memory location at which the magic value is supposed to be - * loaded. This field serves to synchronize the mapping between OS image - * offsets and virtual memory addresses. - * - load_addr - * Contains the virtual address of the beginning of the text segment. The - * offset in the OS image file at which to start loading is defined by the - * offset at which the table was found, minus (header addr - load addr). - * load addr must be less than or equal to header addr. - * - load_end_addr - * Contains the virtual address of the end of the data segment. - * (load_end_addr - load_addr) specifies how much data to load. This implies - * that the text and data segments must be consecutive in the OS image. If - * this field is zero, the domain builder assumes that the text and data - * segments occupy the whole OS image file. - * - bss_end_addr - * Contains the virtual address of the end of the bss segment. The domain - * builder initializes this area to zero, and reserves the memory it occupies - * to avoid placing boot modules and other data relevant to the loaded image - * in that area. If this field is zero, the domain builder assumes that no bss - * segment is present. - * - entry_addr - * The virtual address at which to start execution of the loaded image. - * - * Some of the field descriptions were copied from "The Multiboot - * Specification", Copyright 1995, 96 Bryan Ford <baford@xxxxxxxxxxx>, - * Erich Stefan Boleyn <erich@xxxxxxxx> Copyright 1999, 2000, 2001, 2002 - * Free Software Foundation, Inc. - */ - -#include "xg_private.h" -#include <stdlib.h> - -#define L1_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED) -#define L2_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER) - -#define round_pgup(_p) (((_p)+(PAGE_SIZE-1))&PAGE_MASK) -#define round_pgdown(_p) ((_p)&PAGE_MASK) - -struct xen_bin_image_table -{ - unsigned long magic; - unsigned long flags; - unsigned long checksum; - unsigned long header_addr; - unsigned long load_addr; - unsigned long load_end_addr; - unsigned long bss_end_addr; - unsigned long entry_addr; -}; - -#define XEN_REACTOS_MAGIC3 0x336ec578 - -#define XEN_REACTOS_FLAG_ALIGN4K 0x00000001 -#define XEN_REACTOS_FLAG_NEEDMEMINFO 0x00000002 -#define XEN_REACTOS_FLAG_NEEDVIDINFO 0x00000004 -#define XEN_REACTOS_FLAG_ADDRSVALID 0x00010000 - -/* Flags we test for */ -#define FLAGS_MASK ((~ 0) & (~ XEN_REACTOS_FLAG_ALIGN4K)) -#define FLAGS_REQUIRED XEN_REACTOS_FLAG_ADDRSVALID - -static const struct xen_bin_image_table * -findtable(const char *image, unsigned long image_size); -static int -parsebinimage( - const char *image, unsigned long image_size, - struct domain_setup_info *dsi); -static int -loadbinimage( - const char *image, unsigned long image_size, int xch, uint32_t dom, - xen_pfn_t *parray, struct domain_setup_info *dsi); - -int probe_bin(const char *image, - unsigned long image_size, - struct load_funcs *load_funcs) -{ - if ( findtable(image, image_size) == NULL ) - return -EINVAL; - - load_funcs->parseimage = parsebinimage; - load_funcs->loadimage = loadbinimage; - - return 0; -} - -static const struct xen_bin_image_table * -findtable(const char *image, unsigned long image_size) -{ - const struct xen_bin_image_table *table; - const unsigned long *probe_ptr; - unsigned probe_index; - unsigned probe_count; - - /* Don't go outside the image */ - if ( image_size < sizeof(struct xen_bin_image_table) ) - return NULL; - - probe_count = image_size; - /* Restrict to first 8k */ - if ( probe_count > 8192 ) - probe_count = 8192; - probe_count = (probe_count - sizeof(struct xen_bin_image_table)) / - sizeof(unsigned long); - - /* Search for the magic header */ - probe_ptr = (const unsigned long *) image; - table = NULL; - for ( probe_index = 0; probe_index < probe_count; probe_index++ ) - { - if ( XEN_REACTOS_MAGIC3 == *probe_ptr ) - { - table = (const struct xen_bin_image_table *) probe_ptr; - /* Checksum correct? */ - if ( 0 == table->magic + table->flags + table->checksum ) - { - return table; - } - } - probe_ptr++; - } - - return NULL; -} - -static int parsebinimage(const char *image, - unsigned long image_size, - struct domain_setup_info *dsi) -{ - const struct xen_bin_image_table *image_info; - unsigned long start_addr; - unsigned long end_addr; - - image_info = findtable(image, image_size); - if ( NULL == image_info ) - { - ERROR("Image does not have a valid xen_bin_image_table table."); - return -EINVAL; - } - - /* Check the flags */ - if ( FLAGS_REQUIRED != (image_info->flags & FLAGS_MASK) ) - { - ERROR("xen_bin_image_table flags required 0x%08x found 0x%08lx", - FLAGS_REQUIRED, image_info->flags & FLAGS_MASK); - return -EINVAL; - } - - /* Sanity check on the addresses */ - if ( image_info->header_addr < image_info->load_addr || - ((const char *) image_info - image) < - (image_info->header_addr - image_info->load_addr) ) - { - ERROR("Invalid header_addr."); - return -EINVAL; - } - start_addr = image_info->header_addr - ((const char *) image_info - image); - if ( 0 != image_info->load_end_addr && - ( image_info->load_end_addr < image_info->load_end_addr || - start_addr + image_size < image_info->load_end_addr ) ) - { - ERROR("Invalid load_end_addr"); - return -EINVAL; - } - end_addr = (0 == image_info->load_end_addr ? start_addr + image_size : - image_info->load_end_addr); - if ( 0 != image_info->bss_end_addr && - image_info->bss_end_addr < end_addr ) - { - ERROR("Invalid bss_end_addr"); - return -EINVAL; - } - - dsi->v_start = image_info->load_addr; - if ( 0 != image_info->bss_end_addr ) - { - dsi->v_end = image_info->bss_end_addr; - } - else if ( 0 != image_info->load_end_addr ) - { - dsi->v_end = image_info->load_end_addr; - } - else - { - dsi->v_end = image_info->load_addr + image_size - - (((const char *) image_info - image) - - (image_info->header_addr - image_info->load_addr)); - } - dsi->v_kernstart = dsi->v_start; - dsi->v_kernend = dsi->v_end; - dsi->v_kernentry = image_info->entry_addr; - dsi->__xen_guest_string = NULL; - - return 0; -} - -static int -loadbinimage( - const char *image, unsigned long image_size, int xch, uint32_t dom, - xen_pfn_t *parray, struct domain_setup_info *dsi) -{ - unsigned long size; - char *va; - unsigned long done, chunksz; - const struct xen_bin_image_table *image_info; - - image_info = findtable(image, image_size); - if ( NULL == image_info ) - { - ERROR("Image does not have a valid xen_bin_image_table table."); - return -EINVAL; - } - - /* Determine image size */ - if ( 0 == image_info->load_end_addr ) - { - size = image_size - (((const char *)image_info - image) - - (image_info->header_addr - - image_info->load_addr)); - } - else - { - size = image_info->load_end_addr - image_info->load_addr; - } - - /* It's possible that we need to skip the first part of the image */ - image += ((const char *)image_info - image) - - (image_info->header_addr - image_info->load_addr); - - for ( done = 0; done < size; done += chunksz ) - { - va = xc_map_foreign_range( - xch, dom, PAGE_SIZE, PROT_WRITE, parray[done>>PAGE_SHIFT]); - chunksz = size - done; - if ( chunksz > PAGE_SIZE ) - chunksz = PAGE_SIZE; - memcpy(va, image + done, chunksz); - munmap(va, PAGE_SIZE); - } - - if ( 0 != image_info->bss_end_addr && - image_info->load_addr + size < image_info->bss_end_addr ) - { - size = image_info->bss_end_addr - image_info->load_addr; - } - for ( ; done < size; done += chunksz ) - { - va = xc_map_foreign_range( - xch, dom, PAGE_SIZE, PROT_WRITE, parray[done>>PAGE_SHIFT]); - chunksz = size - done; - if ( chunksz > (PAGE_SIZE - (done & (PAGE_SIZE-1))) ) - chunksz = PAGE_SIZE - (done & (PAGE_SIZE-1)); - memset(va + (done & (PAGE_SIZE-1)), 0, chunksz); - munmap(va, PAGE_SIZE); - } - - return 0; -} - -/* - * Local variables: - * mode: C - * c-set-style: "BSD" - * c-basic-offset: 4 - * tab-width: 4 - * indent-tabs-mode: nil - * End: - */ diff -r 04c23c1ef888 -r d907467f08cd tools/libxc/xc_load_elf.c --- a/tools/libxc/xc_load_elf.c Sun Feb 18 16:13:13 2007 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,684 +0,0 @@ -/****************************************************************************** - * xc_elf_load.c - */ - -#include "xg_private.h" -#include "xc_elf.h" -#include <stdlib.h> -#include <inttypes.h> - -#define round_pgup(_p) (((_p)+(PAGE_SIZE-1))&PAGE_MASK) -#define round_pgdown(_p) ((_p)&PAGE_MASK) - -static int -parseelfimage( - const char *image, unsigned long image_size, - struct domain_setup_info *dsi); -static int -loadelfimage( - const char *image, unsigned long image_size, int xch, uint32_t dom, - xen_pfn_t *parray, struct domain_setup_info *dsi); -static int -loadelfsymtab( - const char *image, int xch, uint32_t dom, xen_pfn_t *parray, - struct domain_setup_info *dsi); - -/* - * Elf header attributes we require for each supported host platform. - * These are checked in parseelfimage(). - */ -#if defined(__ia64__) -#define ELFCLASS ELFCLASS64 -#define ELFCLASS_DESC "64-bit" - -#define ELFDATA ELFDATA2LSB -#define ELFDATA_DESC "Little-Endian" - -#define ELFMACHINE EM_IA_64 -#define ELFMACHINE_DESC "ia64" - - -#elif defined(__i386__) -#define ELFCLASS ELFCLASS32 -#define ELFCLASS_DESC "32-bit" - -#define ELFDATA ELFDATA2LSB -#define ELFDATA_DESC "Little-Endian" - -#define ELFMACHINE EM_386 -#define ELFMACHINE_DESC "i386" - - -#elif defined(__x86_64__) -#define ELFCLASS ELFCLASS64 -#define ELFCLASS_DESC "64-bit" - -#define ELFDATA ELFDATA2LSB -#define ELFDATA_DESC "Little-Endian" - -#define ELFMACHINE EM_X86_64 -#define ELFMACHINE_DESC "x86_64" - - -#elif defined(__powerpc__) -#define ELFCLASS ELFCLASS64 -#define ELFCLASS_DESC "64-bit" - -#define ELFDATA ELFDATA2MSB -#define ELFDATA_DESC "Big-Endian" - -#define ELFMACHINE EM_PPC64 -#define ELFMACHINE_DESC "ppc64" -#endif - -int probe_elf(const char *image, - unsigned long image_size, - struct load_funcs *load_funcs) -{ - const Elf_Ehdr *ehdr = (const Elf_Ehdr *)image; - - if ( !IS_ELF(*ehdr) ) - return -EINVAL; - - load_funcs->parseimage = parseelfimage; - load_funcs->loadimage = loadelfimage; - - return 0; -} - -static inline int is_loadable_phdr(const Elf_Phdr *phdr) -{ - return ((phdr->p_type == PT_LOAD) && - ((phdr->p_flags & (PF_W|PF_X)) != 0)); -} - -/* - * Fallback for kernels containing only the legacy __xen_guest string - * and no ELF notes. - */ -static int is_xen_guest_section(const Elf_Shdr *shdr, const char *shstrtab) -{ - return strcmp(&shstrtab[shdr->sh_name], "__xen_guest") == 0; -} - -static const char *xen_guest_lookup( - const struct domain_setup_info *dsi, int type) -{ - const char *xenguest_fallbacks[] = { - [XEN_ELFNOTE_ENTRY] = "VIRT_ENTRY=", - [XEN_ELFNOTE_HYPERCALL_PAGE] = "HYPERCALL_PAGE=", - [XEN_ELFNOTE_VIRT_BASE] = "VIRT_BASE=", - [XEN_ELFNOTE_PADDR_OFFSET] = "ELF_PADDR_OFFSET=", - [XEN_ELFNOTE_XEN_VERSION] = "XEN_VER=", - [XEN_ELFNOTE_GUEST_OS] = "GUEST_OS=", - [XEN_ELFNOTE_GUEST_VERSION] = "GUEST_VER=", - [XEN_ELFNOTE_LOADER] = "LOADER=", - [XEN_ELFNOTE_PAE_MODE] = "PAE=", - [XEN_ELFNOTE_FEATURES] = "FEATURES=", - [XEN_ELFNOTE_BSD_SYMTAB] = "BSD_SYMTAB=", - }; - const char *fallback; - const char *p; - - if ( !dsi->__xen_guest_string ) - return NULL; - - if ( type > sizeof(xenguest_fallbacks) ) - return NULL; - - if ( (fallback = xenguest_fallbacks[type]) == NULL ) - return NULL; - - if ( (p = strstr(dsi->__xen_guest_string,fallback)) == NULL ) - return NULL; - - return p + strlen(fallback); -} - -static const char *xen_guest_string( - const struct domain_setup_info *dsi, int type) -{ - const char *p = xen_guest_lookup(dsi, type); - - /* - * We special case this since the __xen_guest_section treats the - * mere precense of the BSD_SYMTAB string as true or false. - */ - if ( type == XEN_ELFNOTE_BSD_SYMTAB ) - return p ? "yes" : "no"; - - return p; -} - -static unsigned long long xen_guest_numeric( - const struct domain_setup_info *dsi, int type, int *defined) -{ - const char *p = xen_guest_lookup(dsi, type); - unsigned long long value; - - if ( p == NULL ) - return 0; - - errno = 0; - value = strtoull(p, NULL, 0); - if ( errno < 0 ) - return 0; - - /* We special case this since __xen_guest_section contains a PFN - * for this field not a virtual address. - */ - if (type == XEN_ELFNOTE_HYPERCALL_PAGE) - value = dsi->v_start + (value<<PAGE_SHIFT); - - *defined = 1; - return value; -} - -/* - * Interface to the Xen ELF notes. - */ -#define ELFNOTE_NAME(_n_) ((const char*)(_n_) + sizeof(*(_n_))) -#define ELFNOTE_DESC(_n_) (ELFNOTE_NAME(_n_) + (((_n_)->namesz+3)&~3)) -#define ELFNOTE_NEXT(_n_) (ELFNOTE_DESC(_n_) + (((_n_)->descsz+3)&~3)) - -static int is_xen_elfnote_section(const char *image, const Elf_Shdr *shdr) -{ - const Elf_Note *note; - - if ( shdr->sh_type != SHT_NOTE ) - return 0; - - for ( note = (const Elf_Note *)(image + shdr->sh_offset); - note < (const Elf_Note *)(image + shdr->sh_offset + shdr->sh_size); - note = (const Elf_Note *)ELFNOTE_NEXT(note) ) - { - if ( !strncmp(ELFNOTE_NAME(note), "Xen", 4) ) - return 1; - } - - return 0; -} - -static const Elf_Note *xen_elfnote_lookup( - const struct domain_setup_info *dsi, int type) -{ - const Elf_Note *note; - - if ( !dsi->__elfnote_section ) - return NULL; - - for ( note = (const Elf_Note *)dsi->__elfnote_section; - note < (const Elf_Note *)dsi->__elfnote_section_end; - note = (const Elf_Note *)ELFNOTE_NEXT(note) ) - { - if ( strncmp(ELFNOTE_NAME(note), "Xen", 4) ) - continue; - - if ( note->type == type ) - return note; - } - - return NULL; -} - -const char *xen_elfnote_string(const struct domain_setup_info *dsi, int type) -{ - const Elf_Note *note; - - if ( !dsi->__elfnote_section ) - return xen_guest_string(dsi, type); - - note = xen_elfnote_lookup(dsi, type); - if ( note == NULL ) - return NULL; - - return (const char *)ELFNOTE_DESC(note); -} - -unsigned long long xen_elfnote_numeric(const struct domain_setup_info *dsi, - int type, int *defined) -{ - const Elf_Note *note; - - *defined = 0; - - if ( !dsi->__elfnote_section ) - return xen_guest_numeric(dsi, type, defined); - - note = xen_elfnote_lookup(dsi, type); - if ( note == NULL ) - { - return 0; - } - - switch ( note->descsz ) - { - case 4: - *defined = 1; - return *(const uint32_t*)ELFNOTE_DESC(note); - case 8: - *defined = 1; - return *(const uint64_t*)ELFNOTE_DESC(note); - default: - xc_set_error(XC_INVALID_KERNEL, - "elfnotes: unknown data size %#x for numeric type note %#x\n", - note->descsz, type); - return 0; - } -} - -static int parseelfimage(const char *image, - unsigned long image_len, - struct domain_setup_info *dsi) -{ - const Elf_Ehdr *ehdr = (const Elf_Ehdr *)image; - const Elf_Phdr *phdr; - const Elf_Shdr *shdr; - Elf_Addr kernstart = ~0, kernend = 0, vaddr, virt_entry; - const char *shstrtab, *p; - int h, virt_base_defined, elf_pa_off_defined, virt_entry_defined; - - if ( !IS_ELF(*ehdr) ) - { - xc_set_error(XC_INVALID_KERNEL, - "Kernel image does not have an ELF header."); - return -EINVAL; - } - - if (ehdr->e_machine != ELFMACHINE) - { - xc_set_error(XC_INVALID_KERNEL, - "Kernel ELF architecture '%d' does not match Xen architecture '%d' (%s)", - ehdr->e_machine, ELFMACHINE, ELFMACHINE_DESC); - return -EINVAL; - } - if (ehdr->e_ident[EI_CLASS] != ELFCLASS) - { - xc_set_error(XC_INVALID_KERNEL, - "Kernel ELF wordsize '%d' does not match Xen wordsize '%d' (%s)", - ehdr->e_ident[EI_CLASS], ELFCLASS, ELFCLASS_DESC); - return -EINVAL; - } - if (ehdr->e_ident[EI_DATA] != ELFDATA) - { - xc_set_error(XC_INVALID_KERNEL, - "Kernel ELF endianness '%d' does not match Xen endianness '%d' (%s)", - ehdr->e_ident[EI_DATA], ELFDATA, ELFDATA_DESC); - return -EINVAL; - } - if (ehdr->e_type != ET_EXEC) - { - xc_set_error(XC_INVALID_KERNEL, - "Kernel ELF type '%d' does not match Xen type '%d'", - ehdr->e_type, ET_EXEC); - return -EINVAL; - } - - if ( (ehdr->e_phoff + (ehdr->e_phnum*ehdr->e_phentsize)) > image_len ) - { - xc_set_error(XC_INVALID_KERNEL, - "ELF program headers extend beyond end of image."); - return -EINVAL; - } - - if ( (ehdr->e_shoff + (ehdr->e_shnum*ehdr->e_shentsize)) > image_len ) - { - xc_set_error(XC_INVALID_KERNEL, - "ELF section headers extend beyond end of image."); - return -EINVAL; - } - - dsi->__elfnote_section = NULL; - dsi->__xen_guest_string = NULL; - - /* Look for .notes segment containing at least one Xen note */ - for ( h = 0; h < ehdr->e_shnum; h++ ) - { - shdr = (const Elf_Shdr *)( - image + ehdr->e_shoff + (h*ehdr->e_shentsize)); - if ( !is_xen_elfnote_section(image, shdr) ) - continue; - dsi->__elfnote_section = (const char *)image + shdr->sh_offset; - dsi->__elfnote_section_end = - (const char *)image + shdr->sh_offset + shdr->sh_size; - break; - } - - /* Fall back to looking for the special '__xen_guest' section. */ - if ( dsi->__elfnote_section == NULL ) - { - /* Find the section-header strings table. */ - if ( ehdr->e_shstrndx == SHN_UNDEF ) - { - xc_set_error(XC_INVALID_KERNEL, - "ELF image has no section-header strings table."); - return -EINVAL; - } - shdr = (const Elf_Shdr *)(image + ehdr->e_shoff + - (ehdr->e_shstrndx*ehdr->e_shentsize)); - shstrtab = image + shdr->sh_offset; - - for ( h = 0; h < ehdr->e_shnum; h++ ) - { - shdr = (const Elf_Shdr *)( - image + ehdr->e_shoff + (h*ehdr->e_shentsize)); - if ( is_xen_guest_section(shdr, shstrtab) ) - { - dsi->__xen_guest_string = - (const char *)image + shdr->sh_offset; - break; - } - } - } - - /* Check the contents of the Xen notes or guest string. */ - if ( dsi->__elfnote_section || dsi->__xen_guest_string ) - { - const char *loader = xen_elfnote_string(dsi, XEN_ELFNOTE_LOADER); - const char *guest_os = xen_elfnote_string(dsi, XEN_ELFNOTE_GUEST_OS); - const char *xen_version = - xen_elfnote_string(dsi, XEN_ELFNOTE_XEN_VERSION); - - if ( ( loader == NULL || strncmp(loader, "generic", 7) ) && - ( guest_os == NULL || strncmp(guest_os, "linux", 5) ) ) - { - xc_set_error(XC_INVALID_KERNEL, - "Will only load images built for the generic loader " - "or Linux images"); - return -EINVAL; - } - - if ( xen_version == NULL || strncmp(xen_version, "xen-3.0", 7) ) - { - xc_set_error(XC_INVALID_KERNEL, - "Will only load images built for Xen v3.0"); - return -EINVAL; - } - } - else - { -#if defined(__x86_64__) || defined(__i386__) - xc_set_error(XC_INVALID_KERNEL, - "Not a Xen-ELF image: " - "No ELF notes or '__xen_guest' section found."); - return -EINVAL; -#endif - } - - /* - * A "bimodal" ELF note indicates the kernel will adjust to the current - * paging mode, including handling extended cr3 syntax. If we have ELF - * notes then PAE=yes implies that we must support the extended cr3 syntax. - * Otherwise we need to find the [extended-cr3] syntax in the __xen_guest - * string. We use strstr() to look for "bimodal" to allow guests to use - * "yes,bimodal" or "no,bimodal" for compatibility reasons. - */ - - dsi->pae_kernel = PAEKERN_no; - if ( dsi->__elfnote_section ) - { _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |