diff -r 5abf652c4c52 linux-2.6-xen-sparse/arch/i386/kernel/vmlinux.lds.S --- a/linux-2.6-xen-sparse/arch/i386/kernel/vmlinux.lds.S Tue Feb 21 18:36:00 2006 +++ b/linux-2.6-xen-sparse/arch/i386/kernel/vmlinux.lds.S Wed Feb 22 12:20:06 2006 @@ -10,7 +10,7 @@ OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386") OUTPUT_ARCH(i386) -ENTRY(phys_startup_32) +ENTRY(startup_32) jiffies = jiffies_64; SECTIONS { diff -r 5abf652c4c52 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 Tue Feb 21 18:36:00 2006 +++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/page.h Wed Feb 22 12:20:06 2006 @@ -288,10 +288,6 @@ #endif #define __KERNEL_START (__PAGE_OFFSET + __PHYSICAL_START) -#undef LOAD_OFFSET -#define LOAD_OFFSET 0 - - #define PAGE_OFFSET ((unsigned long)__PAGE_OFFSET) #define VMALLOC_RESERVE ((unsigned long)__VMALLOC_RESERVE) #define MAXMEM (HYPERVISOR_VIRT_START-__PAGE_OFFSET-__VMALLOC_RESERVE) diff -r 5abf652c4c52 tools/libxc/xc_load_elf.c --- a/tools/libxc/xc_load_elf.c Tue Feb 21 18:36:00 2006 +++ b/tools/libxc/xc_load_elf.c Wed Feb 22 12:20:06 2006 @@ -138,10 +138,10 @@ phdr = (Elf_Phdr *)(image + ehdr->e_phoff + (h*ehdr->e_phentsize)); if ( !is_loadable_phdr(phdr) ) continue; - if ( phdr->p_paddr < kernstart ) - kernstart = phdr->p_paddr; - if ( (phdr->p_paddr + phdr->p_memsz) > kernend ) - kernend = phdr->p_paddr + phdr->p_memsz; + if ( phdr->p_vaddr < kernstart ) + kernstart = phdr->p_vaddr; + if ( (phdr->p_vaddr + phdr->p_memsz) > kernend ) + kernend = phdr->p_vaddr + phdr->p_memsz; } if ( (kernstart > kernend) || @@ -189,7 +189,18 @@ for ( done = 0; done < phdr->p_filesz; done += chunksz ) { - pa = (phdr->p_paddr + done) - dsi->v_start; + if (phdr->p_paddr == phdr->p_vaddr) { + /* + * Bug compatibility alert: In older linux kernels + * p_paddr is broken, it doesn't contain the physical + * address but instead is identical to p_vaddr. Thus + * we can't use it directly, instead we'll guess it + * using dsi->v_start. + */ + pa = (phdr->p_vaddr + done) - dsi->v_start; + } else { + pa = (phdr->p_paddr + done); + } va = xc_map_foreign_range( xch, dom, PAGE_SIZE, PROT_WRITE, parray[pa>>PAGE_SHIFT]); chunksz = phdr->p_filesz - done; @@ -202,7 +213,12 @@ for ( ; done < phdr->p_memsz; done += chunksz ) { - pa = (phdr->p_paddr + done) - dsi->v_start; + if (phdr->p_paddr == phdr->p_vaddr) { + /* bug compatibility alert, see above */ + pa = (phdr->p_vaddr + done) - dsi->v_start; + } else { + pa = (phdr->p_paddr + done); + } va = xc_map_foreign_range( xch, dom, PAGE_SIZE, PROT_WRITE, parray[pa>>PAGE_SHIFT]); chunksz = phdr->p_memsz - done; diff -r 5abf652c4c52 xen/arch/x86/domain.c --- a/xen/arch/x86/domain.c Tue Feb 21 18:36:00 2006 +++ b/xen/arch/x86/domain.c Wed Feb 22 12:20:06 2006 @@ -346,7 +346,7 @@ struct vcpu *v, struct vcpu_guest_context *c) { struct domain *d = v->domain; - unsigned long phys_basetab; + unsigned long phys_basetab = 0; int i, rc; /* diff -r 5abf652c4c52 xen/common/elf.c --- a/xen/common/elf.c Tue Feb 21 18:36:00 2006 +++ b/xen/common/elf.c Wed Feb 22 12:20:06 2006 @@ -23,7 +23,8 @@ Elf_Ehdr *ehdr = (Elf_Ehdr *)dsi->image_addr; Elf_Phdr *phdr; Elf_Shdr *shdr; - unsigned long kernstart = ~0UL, kernend=0UL; + unsigned long v_kernstart = ~0UL, v_kernend=0UL; + unsigned long p_kernstart = ~0UL, p_kernend=0UL; char *shstrtab, *guestinfo=NULL, *p; char *elfbase = (char *)dsi->image_addr; int h; @@ -87,21 +88,31 @@ phdr = (Elf_Phdr *)(elfbase + ehdr->e_phoff + (h*ehdr->e_phentsize)); if ( !is_loadable_phdr(phdr) ) continue; - if ( phdr->p_paddr < kernstart ) - kernstart = phdr->p_paddr; - if ( (phdr->p_paddr + phdr->p_memsz) > kernend ) - kernend = phdr->p_paddr + phdr->p_memsz; - } - - if ( (kernstart > kernend) || - (ehdr->e_entry < kernstart) || - (ehdr->e_entry > kernend) ) + printk("%s: phdr: vaddr %08lx paddr %08lx filesz %08lx\n", + __FUNCTION__, + (unsigned long)phdr->p_vaddr, + (unsigned long)phdr->p_paddr, + (unsigned long)phdr->p_filesz); + if ( phdr->p_vaddr < v_kernstart ) + v_kernstart = phdr->p_vaddr; + if ( (phdr->p_vaddr + phdr->p_memsz) > v_kernend ) + v_kernend = phdr->p_vaddr + phdr->p_memsz; + if ( phdr->p_paddr < p_kernstart ) + p_kernstart = phdr->p_paddr; + if ( (phdr->p_paddr + phdr->p_memsz) > p_kernend ) + p_kernend = phdr->p_paddr + phdr->p_memsz; + } + + if ( (v_kernstart > v_kernend) || + (p_kernstart > p_kernend) || + (ehdr->e_entry < v_kernstart) || + (ehdr->e_entry > v_kernend) ) { printk("Malformed ELF image.\n"); return -EINVAL; } - dsi->v_start = kernstart; + dsi->v_start = v_kernstart; if ( guestinfo != NULL ) { @@ -112,10 +123,26 @@ dsi->load_symtab = 1; } - dsi->v_kernstart = kernstart; - dsi->v_kernend = kernend; + dsi->v_kernstart = v_kernstart; + dsi->v_kernend = v_kernend; dsi->v_kernentry = ehdr->e_entry; dsi->v_end = dsi->v_kernend; + + if (p_kernstart == v_kernstart) { + /* + * Bug compatibility alert: In older linux kernels + * p_paddr is broken, it doesn't contain the physical + * address but instead is identical to p_vaddr. Thus + * we can't use it directly, instead we'll guess it + * using dsi->v_start. + */ + printk("%s: linux kernel paddr quirk\n", __FUNCTION__); + dsi->p_kernstart = v_kernstart - dsi->v_start; + dsi->p_kernend = v_kernend - dsi->v_start; + } else { + dsi->p_kernstart = p_kernstart; + dsi->p_kernend = p_kernend; + } loadelfsymtab(dsi, 0); @@ -135,10 +162,10 @@ if ( !is_loadable_phdr(phdr) ) continue; if ( phdr->p_filesz != 0 ) - memcpy((char *)phdr->p_paddr, elfbase + phdr->p_offset, + memcpy((char *)phdr->p_vaddr, elfbase + phdr->p_offset, phdr->p_filesz); if ( phdr->p_memsz > phdr->p_filesz ) - memset((char *)phdr->p_paddr + phdr->p_filesz, 0, + memset((char *)phdr->p_vaddr + phdr->p_filesz, 0, phdr->p_memsz - phdr->p_filesz); } diff -r 5abf652c4c52 xen/include/xen/sched.h --- a/xen/include/xen/sched.h Tue Feb 21 18:36:00 2006 +++ b/xen/include/xen/sched.h Wed Feb 22 12:20:06 2006 @@ -165,6 +165,8 @@ unsigned long v_end; unsigned long v_kernstart; unsigned long v_kernend; + unsigned long p_kernstart; + unsigned long p_kernend; unsigned long v_kernentry; /* Initialised by loader: Private. */ unsigned int load_symtab;