diff options
author | kaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk> | 2004-06-29 16:18:51 +0000 |
---|---|---|
committer | kaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk> | 2004-06-29 16:18:51 +0000 |
commit | fa819b0ee16a650dc4013a7da98e9c9d6e56a1dc (patch) | |
tree | e687b9d58bfe9eabe99ebb72a23babdeccd34b88 | |
parent | 2e18b662f8c13b1bc98426a46999118c84b1c95e (diff) | |
download | xen-fa819b0ee16a650dc4013a7da98e9c9d6e56a1dc.tar.gz xen-fa819b0ee16a650dc4013a7da98e9c9d6e56a1dc.tar.bz2 xen-fa819b0ee16a650dc4013a7da98e9c9d6e56a1dc.zip |
bitkeeper revision 1.1026.3.1 (40e1966bdTS8WBGJY9WhLRE3t6GBdQ)
More cleanups for x86-64.
-rw-r--r-- | .rootkeys | 4 | ||||
-rw-r--r-- | xen/arch/x86/boot/boot.S | 4 | ||||
-rw-r--r-- | xen/arch/x86/mm.c | 2 | ||||
-rw-r--r-- | xen/common/kernel.c | 87 | ||||
-rw-r--r-- | xen/common/memory.c | 21 | ||||
-rw-r--r-- | xen/common/shadow.c | 6 | ||||
-rw-r--r-- | xen/include/asm-x86/config.h | 15 | ||||
-rw-r--r-- | xen/include/asm-x86/page.h | 16 | ||||
-rw-r--r-- | xen/include/asm-x86/string.h | 488 | ||||
-rw-r--r-- | xen/include/asm-x86/types.h | 3 | ||||
-rw-r--r-- | xen/include/asm-x86/x86_32/string.h | 485 | ||||
-rw-r--r-- | xen/include/asm-x86/x86_64/string.h | 69 | ||||
-rw-r--r-- | xen/include/xen/mm.h | 4 |
13 files changed, 663 insertions, 541 deletions
@@ -414,18 +414,20 @@ 3ddb79c3Hgbb2g8CyWLMCK-6_ZVQSQ xen/include/asm-x86/smp.h 3ddb79c3jn8ALV_S9W5aeTYUQRKBpg xen/include/asm-x86/smpboot.h 3ddb79c3NiyQE2vQnyGiaBnNjBO1rA xen/include/asm-x86/spinlock.h -3e7f358aG11EvMI9VJ4_9hD4LUO7rQ xen/include/asm-x86/string.h +40e1966akOHWvvunCED7x3HPv35QvQ xen/include/asm-x86/string.h 3ddb79c3ezddh34MdelJpa5tNR00Dw xen/include/asm-x86/system.h 3ddb79c4HugMq7IYGxcQKFBpKwKhzA xen/include/asm-x86/types.h 40cf1596saFaHD5DC5zvrSn7CDCWGQ xen/include/asm-x86/uaccess.h 3ddb79c2ADvRmdexd9y3AYK9_NTx-Q xen/include/asm-x86/x86_32/current.h 3ddb79c3mbqEM7QQr3zVq7NiBNhouA xen/include/asm-x86/x86_32/ptrace.h +3e7f358aG11EvMI9VJ4_9hD4LUO7rQ xen/include/asm-x86/x86_32/string.h 3ddb79c3M2n1ROZH6xk3HbyN4CPDqg xen/include/asm-x86/x86_32/uaccess.h 404f1b9ceJeGVaPNIENm2FkK0AgEOQ xen/include/asm-x86/x86_64/current.h 404f1b9fl6AQ_a-T1TDK3fuwTPXmHw xen/include/asm-x86/x86_64/desc.h 404f1badfXZJZ2sU8sh9PS2EZvd19Q xen/include/asm-x86/x86_64/ldt.h 404f1bb1LSCqrMDSfRAti5NdMQPJBQ xen/include/asm-x86/x86_64/page.h 404f1bb86rAXB3aLS1vYdcqpJiEcyg xen/include/asm-x86/x86_64/ptrace.h +40e1966azOJZfNI6Ilthe6Q-T3Hewg xen/include/asm-x86/x86_64/string.h 404f1bc4tWkB9Qr8RkKtZGW5eMQzhw xen/include/asm-x86/x86_64/uaccess.h 400304fcmRQmDdFYEzDh0wcBba9alg xen/include/hypervisor-ifs/COPYING 404f1bc68SXxmv0zQpXBWGrCzSyp8w xen/include/hypervisor-ifs/arch-x86_32.h diff --git a/xen/arch/x86/boot/boot.S b/xen/arch/x86/boot/boot.S index ebb74c6562..55a4cc4cc2 100644 --- a/xen/arch/x86/boot/boot.S +++ b/xen/arch/x86/boot/boot.S @@ -101,7 +101,7 @@ continue_boot_cpu: mov 0x4(%eax),%eax /* %eax = mod[mod_count-1]->end */ mov %eax,%ecx sub %ebx,%ecx /* %ecx = byte len of all mods */ - mov $(MAX_DIRECTMAP_ADDRESS), %edi + mov $(DIRECTMAP_PHYS_END), %edi add %ecx, %edi /* %edi = src + length */ shr $2,%ecx /* %ecx = length/4 */ 1: sub $4,%eax /* %eax = src, %edi = dst */ @@ -117,7 +117,7 @@ skip_dom0_copy: 1: mov %eax,__PAGE_OFFSET>>20(%edi) /* high mapping */ stosl /* low mapping */ add $(1<<L2_PAGETABLE_SHIFT),%eax - cmp $MAX_DIRECTMAP_ADDRESS+0x1e3,%eax + cmp $DIRECTMAP_PHYS_END+0x1e3,%eax jne 1b call start_paging diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c index d61df0d9a1..59e304e4a7 100644 --- a/xen/arch/x86/mm.c +++ b/xen/arch/x86/mm.c @@ -347,7 +347,7 @@ void *memguard_init(void *heap_start) PAGE_MASK); /* Memory guarding is incompatible with super pages. */ - for ( i = 0; i < (MAX_XENHEAP_ADDRESS >> L2_PAGETABLE_SHIFT); i++ ) + for ( i = 0; i < (xenheap_phys_end >> L2_PAGETABLE_SHIFT); i++ ) { l1 = (l1_pgentry_t *)heap_start; heap_start = (void *)((unsigned long)heap_start + PAGE_SIZE); diff --git a/xen/common/kernel.c b/xen/common/kernel.c index 001227257e..92602e0bf5 100644 --- a/xen/common/kernel.c +++ b/xen/common/kernel.c @@ -27,6 +27,8 @@ #include <asm/domain_page.h> #include <hypervisor-ifs/dom0_ops.h> +unsigned long xenheap_phys_end; + kmem_cache_t *domain_struct_cachep; struct e820entry { @@ -69,6 +71,11 @@ char opt_physdev_dom0_hide[200] = ""; /* level- or edge-triggered. */ /* Example: 'leveltrigger=4,5,6,20 edgetrigger=21'. */ char opt_leveltrigger[30] = "", opt_edgetrigger[30] = ""; +/* + * opt_xenheap_megabytes: Size of Xen heap in megabytes, excluding the + * pfn_info table and allocation bitmap. + */ +unsigned int opt_xenheap_megabytes = XENHEAP_DEFAULT_MB; static struct { unsigned char *name; @@ -91,6 +98,7 @@ static struct { { "physdev_dom0_hide", OPT_STR, &opt_physdev_dom0_hide }, { "leveltrigger", OPT_STR, &opt_leveltrigger }, { "edgetrigger", OPT_STR, &opt_edgetrigger }, + { "xenheap_megabytes", OPT_UINT, &opt_xenheap_megabytes }, { NULL, 0, NULL } }; @@ -180,52 +188,78 @@ void cmain(unsigned long magic, multiboot_info_t *mbi) for ( ; ; ) ; } + if ( opt_xenheap_megabytes < 4 ) + { + printk("Xen heap size is too small to safely continue!\n"); + for ( ; ; ) ; + } + + set_current(&idle0_task); + + xenheap_phys_end = opt_xenheap_megabytes << 20; + max_mem = max_page = (mbi->mem_upper+1024) >> (PAGE_SHIFT - 10); - /* The array of pfn_info structures must fit into the reserved area. */ - if ( (sizeof(struct pfn_info) * max_page) > - (FRAMETABLE_VIRT_END - FRAMETABLE_VIRT_START) ) +#if defined(__i386__) + + if ( opt_xenheap_megabytes > XENHEAP_DEFAULT_MB ) { - unsigned long new_max = - (FRAMETABLE_VIRT_END - FRAMETABLE_VIRT_START) / - sizeof(struct pfn_info); - printk("Truncating available memory to %lu/%luMB\n", - new_max >> (20 - PAGE_SHIFT), max_page >> (20 - PAGE_SHIFT)); - max_page = new_max; + printk("Xen heap size is limited to %dMB - you specified %dMB.\n", + XENHEAP_DEFAULT_MB, opt_xenheap_megabytes); + for ( ; ; ) ; } - set_current(&idle0_task); + ASSERT((sizeof(struct pfn_info) << 20) > + (FRAMETABLE_VIRT_END - FRAMETABLE_VIRT_START)); - init_frametable(max_page); - printk("Initialised %luMB memory (%lu pages) on a %luMB machine\n", - max_page >> (20-PAGE_SHIFT), max_page, - max_mem >> (20-PAGE_SHIFT)); + init_frametable((void *)FRAMETABLE_VIRT_START, max_page); - initial_images_start = MAX_DIRECTMAP_ADDRESS; + /* Initial images stashed away above DIRECTMAP area in boot.S. */ + initial_images_start = DIRECTMAP_PHYS_END; initial_images_end = initial_images_start + (mod[mbi->mods_count-1].mod_end - mod[0].mod_start); + +#elif defined(__x86_64__) + + init_frametable(__va(xenheap_phys_end), max_page); + + initial_images_start = __pa(frame_table) + frame_table_size; + initial_images_end = initial_images_start + + (mod[mbi->mods_count-1].mod_end - mod[0].mod_start); + if ( initial_images_end > (max_page << PAGE_SHIFT) ) + { + printk("Not enough memory to stash the DOM0 kernel image.\n"); + for ( ; ; ) ; + } + memmove(__va(initial_images_start), + __va(mod[0].mod_start), + mod[mbi->mods_count-1].mod_end - mod[0].mod_start); + +#endif + dom0_memory_start = (initial_images_end + ((4<<20)-1)) & ~((4<<20)-1); dom0_memory_end = dom0_memory_start + (opt_dom0_mem << 10); dom0_memory_end = (dom0_memory_end + PAGE_SIZE - 1) & PAGE_MASK; /* Cheesy sanity check: enough memory for DOM0 allocation + some slack? */ - if ( (dom0_memory_end + (8<<20)) > (max_page<<PAGE_SHIFT) ) - panic("Not enough memory to craete initial domain!\n"); + if ( (dom0_memory_end + (8<<20)) > (max_page << PAGE_SHIFT) ) + { + printk("Not enough memory for DOM0 memory reservation.\n"); + for ( ; ; ) ; + } + + printk("Initialised %luMB memory (%lu pages) on a %luMB machine\n", + max_page >> (20-PAGE_SHIFT), max_page, + max_mem >> (20-PAGE_SHIFT)); add_to_domain_alloc_list(dom0_memory_end, max_page << PAGE_SHIFT); heap_start = memguard_init(&_end); printk("Xen heap size is %luKB\n", - (MAX_XENHEAP_ADDRESS-__pa(heap_start))/1024 ); - - if ( ((MAX_XENHEAP_ADDRESS-__pa(heap_start))/1024) <= 4096 ) - { - printk("Xen heap size is too small to safely continue!\n"); - for ( ; ; ) ; - } + (xenheap_phys_end-__pa(heap_start))/1024 ); - init_page_allocator(__pa(heap_start), MAX_XENHEAP_ADDRESS); + init_page_allocator(__pa(heap_start), xenheap_phys_end); /* Initialise the slab allocator. */ kmem_cache_init(); @@ -253,8 +287,7 @@ void cmain(unsigned long magic, multiboot_info_t *mbi) /* * We're going to setup domain0 using the module(s) that we stashed safely - * above our MAX_DIRECTMAP_ADDRESS in boot/boot.S. The second module, if - * present, is an initrd ramdisk. + * above our heap. The second module, if present, is an initrd ramdisk. */ if ( construct_dom0(new_dom, dom0_memory_start, dom0_memory_end, (char *)initial_images_start, diff --git a/xen/common/memory.c b/xen/common/memory.c index 08e0b05285..4675a95d2e 100644 --- a/xen/common/memory.c +++ b/xen/common/memory.c @@ -144,7 +144,7 @@ static struct { #define GPS (percpu_info[smp_processor_id()].gps ? : current) -void __init init_frametable(unsigned long nr_pages) +void __init init_frametable(void *frametable_vstart, unsigned long nr_pages) { unsigned long mfn; @@ -153,22 +153,23 @@ void __init init_frametable(unsigned long nr_pages) max_page = nr_pages; frame_table_size = nr_pages * sizeof(struct pfn_info); frame_table_size = (frame_table_size + PAGE_SIZE - 1) & PAGE_MASK; - frame_table = (struct pfn_info *)FRAMETABLE_VIRT_START; + frame_table = frametable_vstart; + + if ( (__pa(frame_table) + frame_table_size) > (max_page << PAGE_SHIFT) ) + panic("Not enough memory for frame table - reduce Xen heap size?\n"); + memset(frame_table, 0, frame_table_size); spin_lock_init(&free_list_lock); INIT_LIST_HEAD(&free_list); free_pfns = 0; - /* initialise to a magic of 0x55555555 so easier to spot bugs later */ - memset( machine_to_phys_mapping, 0x55, 4*1024*1024 ); - - /* The array is sized for a 4GB machine regardless of actuall mem size. - This costs 4MB -- may want to fix some day */ + /* Initialise to a magic of 0x55555555 so easier to spot bugs later. */ + memset(machine_to_phys_mapping, 0x55, 4<<20); /* Pin the ownership of the MP table so that DOM0 can map it later. */ - for ( mfn = virt_to_phys(&machine_to_phys_mapping[0])>>PAGE_SHIFT; - mfn < virt_to_phys(&machine_to_phys_mapping[1024*1024])>>PAGE_SHIFT; + for ( mfn = virt_to_phys(&machine_to_phys_mapping[0<<20])>>PAGE_SHIFT; + mfn < virt_to_phys(&machine_to_phys_mapping[1<<20])>>PAGE_SHIFT; mfn++ ) { frame_table[mfn].count_and_flags = 1 | PGC_allocated; @@ -471,6 +472,7 @@ static int alloc_l2_table(struct pfn_info *page) if ( unlikely(!get_page_from_l2e(pl2e[i], page_nr)) ) goto fail; +#if defined(__i386__) /* Now we add our private high mappings. */ memcpy(&pl2e[DOMAIN_ENTRIES_PER_L2_PAGETABLE], &idle_pg_table[DOMAIN_ENTRIES_PER_L2_PAGETABLE], @@ -480,6 +482,7 @@ static int alloc_l2_table(struct pfn_info *page) pl2e[PERDOMAIN_VIRT_START >> L2_PAGETABLE_SHIFT] = mk_l2_pgentry(__pa(page->u.domain->mm.perdomain_pt) | __PAGE_HYPERVISOR); +#endif unmap_domain_mem(pl2e); return 1; diff --git a/xen/common/shadow.c b/xen/common/shadow.c index de5fe4b4fa..dc08bd0199 100644 --- a/xen/common/shadow.c +++ b/xen/common/shadow.c @@ -151,7 +151,9 @@ static inline int shadow_page_op( struct mm_struct *m, unsigned int op, PGT_l2_page_table ) { unsigned long * spl1e = map_domain_mem( spfn<<PAGE_SHIFT ); - memset( spl1e, 0, DOMAIN_ENTRIES_PER_L2_PAGETABLE * sizeof(*spl1e) ); +#ifdef __i386__ + memset(spl1e, 0, DOMAIN_ENTRIES_PER_L2_PAGETABLE * sizeof(*spl1e)); +#endif unmap_domain_mem( spl1e ); } } @@ -574,6 +576,7 @@ unsigned long shadow_l2_table( // we need to do this before the linear map is set up spl2e = (l2_pgentry_t *) map_domain_mem(spfn << PAGE_SHIFT); +#ifdef __i386__ // get hypervisor and 2x linear PT mapings installed memcpy(&spl2e[DOMAIN_ENTRIES_PER_L2_PAGETABLE], &idle_pg_table[DOMAIN_ENTRIES_PER_L2_PAGETABLE], @@ -585,6 +588,7 @@ unsigned long shadow_l2_table( spl2e[PERDOMAIN_VIRT_START >> L2_PAGETABLE_SHIFT] = mk_l2_pgentry(__pa(frame_table[gpfn].u.domain->mm.perdomain_pt) | __PAGE_HYPERVISOR); +#endif // can't use the linear map as we may not be in the right PT gpl2e = (l2_pgentry_t *) map_domain_mem(gpfn << PAGE_SHIFT); diff --git a/xen/include/asm-x86/config.h b/xen/include/asm-x86/config.h index c38304ab8b..af0172df90 100644 --- a/xen/include/asm-x86/config.h +++ b/xen/include/asm-x86/config.h @@ -93,6 +93,8 @@ extern void __out_of_line_bug(int line) __attribute__((noreturn)); #if defined(__x86_64__) +#define XENHEAP_DEFAULT_MB (16) + #define PML4_ENTRY_BITS 39 #define PML4_ENTRY_BYTES (1UL<<PML4_ENTRY_BITS) @@ -158,9 +160,8 @@ extern void __out_of_line_bug(int line) __attribute__((noreturn)); #elif defined(__i386__) -/* The following are machine addresses. */ -#define MAX_XENHEAP_ADDRESS (12*1024*1024) -#define MAX_DIRECTMAP_ADDRESS (40*1024*1024) +#define XENHEAP_DEFAULT_MB (12) +#define DIRECTMAP_PHYS_END (40*1024*1024) /* Hypervisor owns top 64MB of virtual address space. */ #define HYPERVISOR_VIRT_START (0xFC000000UL) @@ -173,9 +174,9 @@ extern void __out_of_line_bug(int line) __attribute__((noreturn)); #define RO_MPT_VIRT_END (RO_MPT_VIRT_START + (4*1024*1024)) /* The virtual addresses for the 40MB direct-map region. */ #define DIRECTMAP_VIRT_START (RO_MPT_VIRT_END) -#define DIRECTMAP_VIRT_END (DIRECTMAP_VIRT_START + MAX_DIRECTMAP_ADDRESS) +#define DIRECTMAP_VIRT_END (DIRECTMAP_VIRT_START + DIRECTMAP_PHYS_END) #define XENHEAP_VIRT_START (DIRECTMAP_VIRT_START) -#define XENHEAP_VIRT_END (XENHEAP_VIRT_START + MAX_XENHEAP_ADDRESS) +#define XENHEAP_VIRT_END (XENHEAP_VIRT_START + (XENHEAP_DEFAULT_MB<<20)) #define RDWR_MPT_VIRT_START (XENHEAP_VIRT_END) #define RDWR_MPT_VIRT_END (RDWR_MPT_VIRT_START + (4*1024*1024)) #define FRAMETABLE_VIRT_START (RDWR_MPT_VIRT_END) @@ -207,6 +208,10 @@ extern void __out_of_line_bug(int line) __attribute__((noreturn)); #endif /* __i386__ */ +#ifndef __ASSEMBLY__ +extern unsigned long xenheap_phys_end; /* user-configurable */ +#endif + #define GDT_VIRT_START (PERDOMAIN_VIRT_START) #define GDT_VIRT_END (GDT_VIRT_START + (64*1024)) #define LDT_VIRT_START (GDT_VIRT_END) diff --git a/xen/include/asm-x86/page.h b/xen/include/asm-x86/page.h index 95cbb4b514..8eb30e35ea 100644 --- a/xen/include/asm-x86/page.h +++ b/xen/include/asm-x86/page.h @@ -95,12 +95,12 @@ typedef struct { unsigned long pt_lo; } pagetable_t; extern l2_pgentry_t idle_pg_table[ENTRIES_PER_L2_PAGETABLE]; extern void paging_init(void); -#define __flush_tlb() \ - do { \ - __asm__ __volatile__ ( \ - "movl %%cr3, %%eax; movl %%eax, %%cr3" \ - : : : "memory", "eax" ); \ - tlb_clocktick(); \ +#define __flush_tlb() \ + do { \ + __asm__ __volatile__ ( \ + "mov %%cr3, %%"__OP"ax; mov %%"__OP"ax, %%cr3" \ + : : : "memory", __OP"ax" ); \ + tlb_clocktick(); \ } while ( 0 ) /* Flush global pages as well. */ @@ -108,14 +108,14 @@ extern void paging_init(void); #define __pge_off() \ do { \ __asm__ __volatile__( \ - "movl %0, %%cr4; # turn off PGE " \ + "mov %0, %%cr4; # turn off PGE " \ :: "r" (mmu_cr4_features & ~X86_CR4_PGE)); \ } while (0) #define __pge_on() \ do { \ __asm__ __volatile__( \ - "movl %0, %%cr4; # turn off PGE " \ + "mov %0, %%cr4; # turn off PGE " \ :: "r" (mmu_cr4_features)); \ } while (0) diff --git a/xen/include/asm-x86/string.h b/xen/include/asm-x86/string.h index 27fbb4d035..fd7ae02a85 100644 --- a/xen/include/asm-x86/string.h +++ b/xen/include/asm-x86/string.h @@ -1,485 +1,5 @@ -#ifndef _I386_STRING_H_ -#define _I386_STRING_H_ - -#include <xen/config.h> - -/* - * This string-include defines all string functions as inline - * functions. Use gcc. It also assumes ds=es=data space, this should be - * normal. Most of the string-functions are rather heavily hand-optimized, - * see especially strtok,strstr,str[c]spn. They should work, but are not - * very easy to understand. Everything is done entirely within the register - * set, making the functions fast and clean. String instructions have been - * used through-out, making for "slightly" unclear code :-) - * - * NO Copyright (C) 1991, 1992 Linus Torvalds, - * consider these trivial functions to be PD. - */ - - -#define __HAVE_ARCH_STRCPY -static inline char * strcpy(char * dest,const char *src) -{ -int d0, d1, d2; -__asm__ __volatile__( - "1:\tlodsb\n\t" - "stosb\n\t" - "testb %%al,%%al\n\t" - "jne 1b" - : "=&S" (d0), "=&D" (d1), "=&a" (d2) - :"0" (src),"1" (dest) : "memory"); -return dest; -} - -#define __HAVE_ARCH_STRNCPY -static inline char * strncpy(char * dest,const char *src,size_t count) -{ -int d0, d1, d2, d3; -__asm__ __volatile__( - "1:\tdecl %2\n\t" - "js 2f\n\t" - "lodsb\n\t" - "stosb\n\t" - "testb %%al,%%al\n\t" - "jne 1b\n\t" - "rep\n\t" - "stosb\n" - "2:" - : "=&S" (d0), "=&D" (d1), "=&c" (d2), "=&a" (d3) - :"0" (src),"1" (dest),"2" (count) : "memory"); -return dest; -} - -#define __HAVE_ARCH_STRCAT -static inline char * strcat(char * dest,const char * src) -{ -int d0, d1, d2, d3; -__asm__ __volatile__( - "repne\n\t" - "scasb\n\t" - "decl %1\n" - "1:\tlodsb\n\t" - "stosb\n\t" - "testb %%al,%%al\n\t" - "jne 1b" - : "=&S" (d0), "=&D" (d1), "=&a" (d2), "=&c" (d3) - : "0" (src), "1" (dest), "2" (0), "3" (0xffffffff):"memory"); -return dest; -} - -#define __HAVE_ARCH_STRNCAT -static inline char * strncat(char * dest,const char * src,size_t count) -{ -int d0, d1, d2, d3; -__asm__ __volatile__( - "repne\n\t" - "scasb\n\t" - "decl %1\n\t" - "movl %8,%3\n" - "1:\tdecl %3\n\t" - "js 2f\n\t" - "lodsb\n\t" - "stosb\n\t" - "testb %%al,%%al\n\t" - "jne 1b\n" - "2:\txorl %2,%2\n\t" - "stosb" - : "=&S" (d0), "=&D" (d1), "=&a" (d2), "=&c" (d3) - : "0" (src),"1" (dest),"2" (0),"3" (0xffffffff), "g" (count) - : "memory"); -return dest; -} - -#define __HAVE_ARCH_STRCMP -static inline int strcmp(const char * cs,const char * ct) -{ -int d0, d1; -register int __res; -__asm__ __volatile__( - "1:\tlodsb\n\t" - "scasb\n\t" - "jne 2f\n\t" - "testb %%al,%%al\n\t" - "jne 1b\n\t" - "xorl %%eax,%%eax\n\t" - "jmp 3f\n" - "2:\tsbbl %%eax,%%eax\n\t" - "orb $1,%%al\n" - "3:" - :"=a" (__res), "=&S" (d0), "=&D" (d1) - :"1" (cs),"2" (ct)); -return __res; -} - -#define __HAVE_ARCH_STRNCMP -static inline int strncmp(const char * cs,const char * ct,size_t count) -{ -register int __res; -int d0, d1, d2; -__asm__ __volatile__( - "1:\tdecl %3\n\t" - "js 2f\n\t" - "lodsb\n\t" - "scasb\n\t" - "jne 3f\n\t" - "testb %%al,%%al\n\t" - "jne 1b\n" - "2:\txorl %%eax,%%eax\n\t" - "jmp 4f\n" - "3:\tsbbl %%eax,%%eax\n\t" - "orb $1,%%al\n" - "4:" - :"=a" (__res), "=&S" (d0), "=&D" (d1), "=&c" (d2) - :"1" (cs),"2" (ct),"3" (count)); -return __res; -} - -#define __HAVE_ARCH_STRCHR -static inline char * strchr(const char * s, int c) -{ -int d0; -register char * __res; -__asm__ __volatile__( - "movb %%al,%%ah\n" - "1:\tlodsb\n\t" - "cmpb %%ah,%%al\n\t" - "je 2f\n\t" - "testb %%al,%%al\n\t" - "jne 1b\n\t" - "movl $1,%1\n" - "2:\tmovl %1,%0\n\t" - "decl %0" - :"=a" (__res), "=&S" (d0) : "1" (s),"0" (c)); -return __res; -} - -#define __HAVE_ARCH_STRRCHR -static inline char * strrchr(const char * s, int c) -{ -int d0, d1; -register char * __res; -__asm__ __volatile__( - "movb %%al,%%ah\n" - "1:\tlodsb\n\t" - "cmpb %%ah,%%al\n\t" - "jne 2f\n\t" - "leal -1(%%esi),%0\n" - "2:\ttestb %%al,%%al\n\t" - "jne 1b" - :"=g" (__res), "=&S" (d0), "=&a" (d1) :"0" (0),"1" (s),"2" (c)); -return __res; -} - -#define __HAVE_ARCH_STRLEN -static inline size_t strlen(const char * s) -{ -int d0; -register int __res; -__asm__ __volatile__( - "repne\n\t" - "scasb\n\t" - "notl %0\n\t" - "decl %0" - :"=c" (__res), "=&D" (d0) :"1" (s),"a" (0), "0" (0xffffffff)); -return __res; -} - -static inline void * __memcpy(void * to, const void * from, size_t n) -{ -int d0, d1, d2; -__asm__ __volatile__( - "rep ; movsl\n\t" - "testb $2,%b4\n\t" - "je 1f\n\t" - "movsw\n" - "1:\ttestb $1,%b4\n\t" - "je 2f\n\t" - "movsb\n" - "2:" - : "=&c" (d0), "=&D" (d1), "=&S" (d2) - :"0" (n/4), "q" (n),"1" ((long) to),"2" ((long) from) - : "memory"); -return (to); -} - -/* - * This looks horribly ugly, but the compiler can optimize it totally, - * as the count is constant. - */ -static inline void * __constant_memcpy(void * to, const void * from, size_t n) -{ - switch (n) { - case 0: - return to; - case 1: - *(unsigned char *)to = *(const unsigned char *)from; - return to; - case 2: - *(unsigned short *)to = *(const unsigned short *)from; - return to; - case 3: - *(unsigned short *)to = *(const unsigned short *)from; - *(2+(unsigned char *)to) = *(2+(const unsigned char *)from); - return to; - case 4: - *(unsigned long *)to = *(const unsigned long *)from; - return to; - case 6: /* for Ethernet addresses */ - *(unsigned long *)to = *(const unsigned long *)from; - *(2+(unsigned short *)to) = *(2+(const unsigned short *)from); - return to; - case 8: - *(unsigned long *)to = *(const unsigned long *)from; - *(1+(unsigned long *)to) = *(1+(const unsigned long *)from); - return to; - case 12: - *(unsigned long *)to = *(const unsigned long *)from; - *(1+(unsigned long *)to) = *(1+(const unsigned long *)from); - *(2+(unsigned long *)to) = *(2+(const unsigned long *)from); - return to; - case 16: - *(unsigned long *)to = *(const unsigned long *)from; - *(1+(unsigned long *)to) = *(1+(const unsigned long *)from); - *(2+(unsigned long *)to) = *(2+(const unsigned long *)from); - *(3+(unsigned long *)to) = *(3+(const unsigned long *)from); - return to; - case 20: - *(unsigned long *)to = *(const unsigned long *)from; - *(1+(unsigned long *)to) = *(1+(const unsigned long *)from); - *(2+(unsigned long *)to) = *(2+(const unsigned long *)from); - *(3+(unsigned long *)to) = *(3+(const unsigned long *)from); - *(4+(unsigned long *)to) = *(4+(const unsigned long *)from); - return to; - } -#define COMMON(x) \ -__asm__ __volatile__( \ - "rep ; movsl" \ - x \ - : "=&c" (d0), "=&D" (d1), "=&S" (d2) \ - : "0" (n/4),"1" ((long) to),"2" ((long) from) \ - : "memory"); -{ - int d0, d1, d2; - switch (n % 4) { - case 0: COMMON(""); return to; - case 1: COMMON("\n\tmovsb"); return to; - case 2: COMMON("\n\tmovsw"); return to; - default: COMMON("\n\tmovsw\n\tmovsb"); return to; - } -} - -#undef COMMON -} - -#define __HAVE_ARCH_MEMCPY - -#define memcpy(t, f, n) \ -(__builtin_constant_p(n) ? \ - __constant_memcpy((t),(f),(n)) : \ - __memcpy((t),(f),(n))) - - -/* - * struct_cpy(x,y), copy structure *x into (matching structure) *y. - * - * We get link-time errors if the structure sizes do not match. - * There is no runtime overhead, it's all optimized away at - * compile time. - */ -//extern void __struct_cpy_bug (void); - -/* -#define struct_cpy(x,y) \ -({ \ - if (sizeof(*(x)) != sizeof(*(y))) \ - __struct_cpy_bug; \ - memcpy(x, y, sizeof(*(x))); \ -}) -*/ - -#define __HAVE_ARCH_MEMMOVE -static inline void * memmove(void * dest,const void * src, size_t n) -{ -int d0, d1, d2; -if (dest<src) -__asm__ __volatile__( - "rep\n\t" - "movsb" - : "=&c" (d0), "=&S" (d1), "=&D" (d2) - :"0" (n),"1" (src),"2" (dest) - : "memory"); -else -__asm__ __volatile__( - "std\n\t" - "rep\n\t" - "movsb\n\t" - "cld" - : "=&c" (d0), "=&S" (d1), "=&D" (d2) - :"0" (n), - "1" (n-1+(const char *)src), - "2" (n-1+(char *)dest) - :"memory"); -return dest; -} - -#define __HAVE_ARCH_MEMCMP -#define memcmp __builtin_memcmp - -#define __HAVE_ARCH_MEMCHR -static inline void * memchr(const void * cs,int c,size_t count) -{ -int d0; -register void * __res; -if (!count) - return NULL; -__asm__ __volatile__( - "repne\n\t" - "scasb\n\t" - "je 1f\n\t" - "movl $1,%0\n" - "1:\tdecl %0" - :"=D" (__res), "=&c" (d0) : "a" (c),"0" (cs),"1" (count)); -return __res; -} - -static inline void * __memset_generic(void * s, char c,size_t count) -{ -int d0, d1; -__asm__ __volatile__( - "rep\n\t" - "stosb" - : "=&c" (d0), "=&D" (d1) - :"a" (c),"1" (s),"0" (count) - :"memory"); -return s; -} - -/* we might want to write optimized versions of these later */ -#define __constant_count_memset(s,c,count) __memset_generic((s),(c),(count)) - -/* - * memset(x,0,y) is a reasonably common thing to do, so we want to fill - * things 32 bits at a time even when we don't know the size of the - * area at compile-time.. - */ -static inline void * __constant_c_memset(void * s, unsigned long c, size_t count) -{ -int d0, d1; -__asm__ __volatile__( - "rep ; stosl\n\t" - "testb $2,%b3\n\t" - "je 1f\n\t" - "stosw\n" - "1:\ttestb $1,%b3\n\t" - "je 2f\n\t" - "stosb\n" - "2:" - : "=&c" (d0), "=&D" (d1) - :"a" (c), "q" (count), "0" (count/4), "1" ((long) s) - :"memory"); -return (s); -} - -/* Added by Gertjan van Wingerde to make minix and sysv module work */ -#define __HAVE_ARCH_STRNLEN -static inline size_t strnlen(const char * s, size_t count) -{ -int d0; -register int __res; -__asm__ __volatile__( - "movl %2,%0\n\t" - "jmp 2f\n" - "1:\tcmpb $0,(%0)\n\t" - "je 3f\n\t" - "incl %0\n" - "2:\tdecl %1\n\t" - "cmpl $-1,%1\n\t" - "jne 1b\n" - "3:\tsubl %2,%0" - :"=a" (__res), "=&d" (d0) - :"c" (s),"1" (count)); -return __res; -} -/* end of additional stuff */ - -//#define __HAVE_ARCH_STRSTR - -//extern char *strstr(const char *cs, const char *ct); - -/* - * This looks horribly ugly, but the compiler can optimize it totally, - * as we by now know that both pattern and count is constant.. - */ -static inline void * __constant_c_and_count_memset(void * s, unsigned long pattern, size_t count) -{ - switch (count) { - case 0: - return s; - case 1: - *(unsigned char *)s = pattern; - return s; - case 2: - *(unsigned short *)s = pattern; - return s; - case 3: - *(unsigned short *)s = pattern; - *(2+(unsigned char *)s) = pattern; - return s; - case 4: - *(unsigned long *)s = pattern; - return s; - } -#define COMMON(x) \ -__asm__ __volatile__( \ - "rep ; stosl" \ - x \ - : "=&c" (d0), "=&D" (d1) \ - : "a" (pattern),"0" (count/4),"1" ((long) s) \ - : "memory") -{ - int d0, d1; - switch (count % 4) { - case 0: COMMON(""); return s; - case 1: COMMON("\n\tstosb"); return s; - case 2: COMMON("\n\tstosw"); return s; - default: COMMON("\n\tstosw\n\tstosb"); return s; - } -} - -#undef COMMON -} - -#define __constant_c_x_memset(s, c, count) \ -(__builtin_constant_p(count) ? \ - __constant_c_and_count_memset((s),(c),(count)) : \ - __constant_c_memset((s),(c),(count))) - -#define __memset(s, c, count) \ -(__builtin_constant_p(count) ? \ - __constant_count_memset((s),(c),(count)) : \ - __memset_generic((s),(c),(count))) - -#define __HAVE_ARCH_MEMSET -#define memset(s, c, count) \ -(__builtin_constant_p(c) ? \ - __constant_c_x_memset((s),(0x01010101UL*(unsigned char)(c)),(count)) : \ - __memset((s),(c),(count))) - -/* - * find the first occurrence of byte 'c', or 1 past the area if none - */ -#define __HAVE_ARCH_MEMSCAN -static inline void * memscan(void * addr, int c, size_t size) -{ - if (!size) - return addr; - __asm__("repnz; scasb\n\t" - "jnz 1f\n\t" - "dec %%edi\n" - "1:" - : "=D" (addr), "=c" (size) - : "0" (addr), "1" (size), "a" (c)); - return addr; -} - +#ifdef __x86_64__ +#include <asm/x86_64/string.h> +#else +#include <asm/x86_32/string.h> #endif diff --git a/xen/include/asm-x86/types.h b/xen/include/asm-x86/types.h index 0b4b616b24..e2b229edcf 100644 --- a/xen/include/asm-x86/types.h +++ b/xen/include/asm-x86/types.h @@ -3,7 +3,6 @@ typedef unsigned short umode_t; -typedef unsigned int size_t; /* * __xx is ok: it doesn't pollute the POSIX namespace. Use these in the @@ -44,10 +43,12 @@ typedef unsigned int u32; typedef signed long long s64; typedef unsigned long long u64; #define BITS_PER_LONG 32 +typedef unsigned int size_t; #elif defined(__x86_64__) typedef signed long s64; typedef unsigned long u64; #define BITS_PER_LONG 64 +typedef unsigned long size_t; #endif /* DMA addresses come in generic and 64-bit flavours. */ diff --git a/xen/include/asm-x86/x86_32/string.h b/xen/include/asm-x86/x86_32/string.h new file mode 100644 index 0000000000..27fbb4d035 --- /dev/null +++ b/xen/include/asm-x86/x86_32/string.h @@ -0,0 +1,485 @@ +#ifndef _I386_STRING_H_ +#define _I386_STRING_H_ + +#include <xen/config.h> + +/* + * This string-include defines all string functions as inline + * functions. Use gcc. It also assumes ds=es=data space, this should be + * normal. Most of the string-functions are rather heavily hand-optimized, + * see especially strtok,strstr,str[c]spn. They should work, but are not + * very easy to understand. Everything is done entirely within the register + * set, making the functions fast and clean. String instructions have been + * used through-out, making for "slightly" unclear code :-) + * + * NO Copyright (C) 1991, 1992 Linus Torvalds, + * consider these trivial functions to be PD. + */ + + +#define __HAVE_ARCH_STRCPY +static inline char * strcpy(char * dest,const char *src) +{ +int d0, d1, d2; +__asm__ __volatile__( + "1:\tlodsb\n\t" + "stosb\n\t" + "testb %%al,%%al\n\t" + "jne 1b" + : "=&S" (d0), "=&D" (d1), "=&a" (d2) + :"0" (src),"1" (dest) : "memory"); +return dest; +} + +#define __HAVE_ARCH_STRNCPY +static inline char * strncpy(char * dest,const char *src,size_t count) +{ +int d0, d1, d2, d3; +__asm__ __volatile__( + "1:\tdecl %2\n\t" + "js 2f\n\t" + "lodsb\n\t" + "stosb\n\t" + "testb %%al,%%al\n\t" + "jne 1b\n\t" + "rep\n\t" + "stosb\n" + "2:" + : "=&S" (d0), "=&D" (d1), "=&c" (d2), "=&a" (d3) + :"0" (src),"1" (dest),"2" (count) : "memory"); +return dest; +} + +#define __HAVE_ARCH_STRCAT +static inline char * strcat(char * dest,const char * src) +{ +int d0, d1, d2, d3; +__asm__ __volatile__( + "repne\n\t" + "scasb\n\t" + "decl %1\n" + "1:\tlodsb\n\t" + "stosb\n\t" + "testb %%al,%%al\n\t" + "jne 1b" + : "=&S" (d0), "=&D" (d1), "=&a" (d2), "=&c" (d3) + : "0" (src), "1" (dest), "2" (0), "3" (0xffffffff):"memory"); +return dest; +} + +#define __HAVE_ARCH_STRNCAT +static inline char * strncat(char * dest,const char * src,size_t count) +{ +int d0, d1, d2, d3; +__asm__ __volatile__( + "repne\n\t" + "scasb\n\t" + "decl %1\n\t" + "movl %8,%3\n" + "1:\tdecl %3\n\t" + "js 2f\n\t" + "lodsb\n\t" + "stosb\n\t" + "testb %%al,%%al\n\t" + "jne 1b\n" + "2:\txorl %2,%2\n\t" + "stosb" + : "=&S" (d0), "=&D" (d1), "=&a" (d2), "=&c" (d3) + : "0" (src),"1" (dest),"2" (0),"3" (0xffffffff), "g" (count) + : "memory"); +return dest; +} + +#define __HAVE_ARCH_STRCMP +static inline int strcmp(const char * cs,const char * ct) +{ +int d0, d1; +register int __res; +__asm__ __volatile__( + "1:\tlodsb\n\t" + "scasb\n\t" + "jne 2f\n\t" + "testb %%al,%%al\n\t" + "jne 1b\n\t" + "xorl %%eax,%%eax\n\t" + "jmp 3f\n" + "2:\tsbbl %%eax,%%eax\n\t" + "orb $1,%%al\n" + "3:" + :"=a" (__res), "=&S" (d0), "=&D" (d1) + :"1" (cs),"2" (ct)); +return __res; +} + +#define __HAVE_ARCH_STRNCMP +static inline int strncmp(const char * cs,const char * ct,size_t count) +{ +register int __res; +int d0, d1, d2; +__asm__ __volatile__( + "1:\tdecl %3\n\t" + "js 2f\n\t" + "lodsb\n\t" + "scasb\n\t" + "jne 3f\n\t" + "testb %%al,%%al\n\t" + "jne 1b\n" + "2:\txorl %%eax,%%eax\n\t" + "jmp 4f\n" + "3:\tsbbl %%eax,%%eax\n\t" + "orb $1,%%al\n" + "4:" + :"=a" (__res), "=&S" (d0), "=&D" (d1), "=&c" (d2) + :"1" (cs),"2" (ct),"3" (count)); +return __res; +} + +#define __HAVE_ARCH_STRCHR +static inline char * strchr(const char * s, int c) +{ +int d0; +register char * __res; +__asm__ __volatile__( + "movb %%al,%%ah\n" + "1:\tlodsb\n\t" + "cmpb %%ah,%%al\n\t" + "je 2f\n\t" + "testb %%al,%%al\n\t" + "jne 1b\n\t" + "movl $1,%1\n" + "2:\tmovl %1,%0\n\t" + "decl %0" + :"=a" (__res), "=&S" (d0) : "1" (s),"0" (c)); +return __res; +} + +#define __HAVE_ARCH_STRRCHR +static inline char * strrchr(const char * s, int c) +{ +int d0, d1; +register char * __res; +__asm__ __volatile__( + "movb %%al,%%ah\n" + "1:\tlodsb\n\t" + "cmpb %%ah,%%al\n\t" + "jne 2f\n\t" + "leal -1(%%esi),%0\n" + "2:\ttestb %%al,%%al\n\t" + "jne 1b" + :"=g" (__res), "=&S" (d0), "=&a" (d1) :"0" (0),"1" (s),"2" (c)); +return __res; +} + +#define __HAVE_ARCH_STRLEN +static inline size_t strlen(const char * s) +{ +int d0; +register int __res; +__asm__ __volatile__( + "repne\n\t" + "scasb\n\t" + "notl %0\n\t" + "decl %0" + :"=c" (__res), "=&D" (d0) :"1" (s),"a" (0), "0" (0xffffffff)); +return __res; +} + +static inline void * __memcpy(void * to, const void * from, size_t n) +{ +int d0, d1, d2; +__asm__ __volatile__( + "rep ; movsl\n\t" + "testb $2,%b4\n\t" + "je 1f\n\t" + "movsw\n" + "1:\ttestb $1,%b4\n\t" + "je 2f\n\t" + "movsb\n" + "2:" + : "=&c" (d0), "=&D" (d1), "=&S" (d2) + :"0" (n/4), "q" (n),"1" ((long) to),"2" ((long) from) + : "memory"); +return (to); +} + +/* + * This looks horribly ugly, but the compiler can optimize it totally, + * as the count is constant. + */ +static inline void * __constant_memcpy(void * to, const void * from, size_t n) +{ + switch (n) { + case 0: + return to; + case 1: + *(unsigned char *)to = *(const unsigned char *)from; + return to; + case 2: + *(unsigned short *)to = *(const unsigned short *)from; + return to; + case 3: + *(unsigned short *)to = *(const unsigned short *)from; + *(2+(unsigned char *)to) = *(2+(const unsigned char *)from); + return to; + case 4: + *(unsigned long *)to = *(const unsigned long *)from; + return to; + case 6: /* for Ethernet addresses */ + *(unsigned long *)to = *(const unsigned long *)from; + *(2+(unsigned short *)to) = *(2+(const unsigned short *)from); + return to; + case 8: + *(unsigned long *)to = *(const unsigned long *)from; + *(1+(unsigned long *)to) = *(1+(const unsigned long *)from); + return to; + case 12: + *(unsigned long *)to = *(const unsigned long *)from; + *(1+(unsigned long *)to) = *(1+(const unsigned long *)from); + *(2+(unsigned long *)to) = *(2+(const unsigned long *)from); + return to; + case 16: + *(unsigned long *)to = *(const unsigned long *)from; + *(1+(unsigned long *)to) = *(1+(const unsigned long *)from); + *(2+(unsigned long *)to) = *(2+(const unsigned long *)from); + *(3+(unsigned long *)to) = *(3+(const unsigned long *)from); + return to; + case 20: + *(unsigned long *)to = *(const unsigned long *)from; + *(1+(unsigned long *)to) = *(1+(const unsigned long *)from); + *(2+(unsigned long *)to) = *(2+(const unsigned long *)from); + *(3+(unsigned long *)to) = *(3+(const unsigned long *)from); + *(4+(unsigned long *)to) = *(4+(const unsigned long *)from); + return to; + } +#define COMMON(x) \ +__asm__ __volatile__( \ + "rep ; movsl" \ + x \ + : "=&c" (d0), "=&D" (d1), "=&S" (d2) \ + : "0" (n/4),"1" ((long) to),"2" ((long) from) \ + : "memory"); +{ + int d0, d1, d2; + switch (n % 4) { + case 0: COMMON(""); return to; + case 1: COMMON("\n\tmovsb"); return to; + case 2: COMMON("\n\tmovsw"); return to; + default: COMMON("\n\tmovsw\n\tmovsb"); return to; + } +} + +#undef COMMON +} + +#define __HAVE_ARCH_MEMCPY + +#define memcpy(t, f, n) \ +(__builtin_constant_p(n) ? \ + __constant_memcpy((t),(f),(n)) : \ + __memcpy((t),(f),(n))) + + +/* + * struct_cpy(x,y), copy structure *x into (matching structure) *y. + * + * We get link-time errors if the structure sizes do not match. + * There is no runtime overhead, it's all optimized away at + * compile time. + */ +//extern void __struct_cpy_bug (void); + +/* +#define struct_cpy(x,y) \ +({ \ + if (sizeof(*(x)) != sizeof(*(y))) \ + __struct_cpy_bug; \ + memcpy(x, y, sizeof(*(x))); \ +}) +*/ + +#define __HAVE_ARCH_MEMMOVE +static inline void * memmove(void * dest,const void * src, size_t n) +{ +int d0, d1, d2; +if (dest<src) +__asm__ __volatile__( + "rep\n\t" + "movsb" + : "=&c" (d0), "=&S" (d1), "=&D" (d2) + :"0" (n),"1" (src),"2" (dest) + : "memory"); +else +__asm__ __volatile__( + "std\n\t" + "rep\n\t" + "movsb\n\t" + "cld" + : "=&c" (d0), "=&S" (d1), "=&D" (d2) + :"0" (n), + "1" (n-1+(const char *)src), + "2" (n-1+(char *)dest) + :"memory"); +return dest; +} + +#define __HAVE_ARCH_MEMCMP +#define memcmp __builtin_memcmp + +#define __HAVE_ARCH_MEMCHR +static inline void * memchr(const void * cs,int c,size_t count) +{ +int d0; +register void * __res; +if (!count) + return NULL; +__asm__ __volatile__( + "repne\n\t" + "scasb\n\t" + "je 1f\n\t" + "movl $1,%0\n" + "1:\tdecl %0" + :"=D" (__res), "=&c" (d0) : "a" (c),"0" (cs),"1" (count)); +return __res; +} + +static inline void * __memset_generic(void * s, char c,size_t count) +{ +int d0, d1; +__asm__ __volatile__( + "rep\n\t" + "stosb" + : "=&c" (d0), "=&D" (d1) + :"a" (c),"1" (s),"0" (count) + :"memory"); +return s; +} + +/* we might want to write optimized versions of these later */ +#define __constant_count_memset(s,c,count) __memset_generic((s),(c),(count)) + +/* + * memset(x,0,y) is a reasonably common thing to do, so we want to fill + * things 32 bits at a time even when we don't know the size of the + * area at compile-time.. + */ +static inline void * __constant_c_memset(void * s, unsigned long c, size_t count) +{ +int d0, d1; +__asm__ __volatile__( + "rep ; stosl\n\t" + "testb $2,%b3\n\t" + "je 1f\n\t" + "stosw\n" + "1:\ttestb $1,%b3\n\t" + "je 2f\n\t" + "stosb\n" + "2:" + : "=&c" (d0), "=&D" (d1) + :"a" (c), "q" (count), "0" (count/4), "1" ((long) s) + :"memory"); +return (s); +} + +/* Added by Gertjan van Wingerde to make minix and sysv module work */ +#define __HAVE_ARCH_STRNLEN +static inline size_t strnlen(const char * s, size_t count) +{ +int d0; +register int __res; +__asm__ __volatile__( + "movl %2,%0\n\t" + "jmp 2f\n" + "1:\tcmpb $0,(%0)\n\t" + "je 3f\n\t" + "incl %0\n" + "2:\tdecl %1\n\t" + "cmpl $-1,%1\n\t" + "jne 1b\n" + "3:\tsubl %2,%0" + :"=a" (__res), "=&d" (d0) + :"c" (s),"1" (count)); +return __res; +} +/* end of additional stuff */ + +//#define __HAVE_ARCH_STRSTR + +//extern char *strstr(const char *cs, const char *ct); + +/* + * This looks horribly ugly, but the compiler can optimize it totally, + * as we by now know that both pattern and count is constant.. + */ +static inline void * __constant_c_and_count_memset(void * s, unsigned long pattern, size_t count) +{ + switch (count) { + case 0: + return s; + case 1: + *(unsigned char *)s = pattern; + return s; + case 2: + *(unsigned short *)s = pattern; + return s; + case 3: + *(unsigned short *)s = pattern; + *(2+(unsigned char *)s) = pattern; + return s; + case 4: + *(unsigned long *)s = pattern; + return s; + } +#define COMMON(x) \ +__asm__ __volatile__( \ + "rep ; stosl" \ + x \ + : "=&c" (d0), "=&D" (d1) \ + : "a" (pattern),"0" (count/4),"1" ((long) s) \ + : "memory") +{ + int d0, d1; + switch (count % 4) { + case 0: COMMON(""); return s; + case 1: COMMON("\n\tstosb"); return s; + case 2: COMMON("\n\tstosw"); return s; + default: COMMON("\n\tstosw\n\tstosb"); return s; + } +} + +#undef COMMON +} + +#define __constant_c_x_memset(s, c, count) \ +(__builtin_constant_p(count) ? \ + __constant_c_and_count_memset((s),(c),(count)) : \ + __constant_c_memset((s),(c),(count))) + +#define __memset(s, c, count) \ +(__builtin_constant_p(count) ? \ + __constant_count_memset((s),(c),(count)) : \ + __memset_generic((s),(c),(count))) + +#define __HAVE_ARCH_MEMSET +#define memset(s, c, count) \ +(__builtin_constant_p(c) ? \ + __constant_c_x_memset((s),(0x01010101UL*(unsigned char)(c)),(count)) : \ + __memset((s),(c),(count))) + +/* + * find the first occurrence of byte 'c', or 1 past the area if none + */ +#define __HAVE_ARCH_MEMSCAN +static inline void * memscan(void * addr, int c, size_t size) +{ + if (!size) + return addr; + __asm__("repnz; scasb\n\t" + "jnz 1f\n\t" + "dec %%edi\n" + "1:" + : "=D" (addr), "=c" (size) + : "0" (addr), "1" (size), "a" (c)); + return addr; +} + +#endif diff --git a/xen/include/asm-x86/x86_64/string.h b/xen/include/asm-x86/x86_64/string.h new file mode 100644 index 0000000000..27876b9da0 --- /dev/null +++ b/xen/include/asm-x86/x86_64/string.h @@ -0,0 +1,69 @@ +#ifndef _X86_64_STRING_H_ +#define _X86_64_STRING_H_ + +#ifdef __KERNEL__ + +#define struct_cpy(x,y) (*(x)=*(y)) + +/* Written 2002 by Andi Kleen */ + +/* Only used for special circumstances. Stolen from i386/string.h */ +static inline void * __inline_memcpy(void * to, const void * from, size_t n) +{ +unsigned long d0, d1, d2; +__asm__ __volatile__( + "rep ; movsl\n\t" + "testb $2,%b4\n\t" + "je 1f\n\t" + "movsw\n" + "1:\ttestb $1,%b4\n\t" + "je 2f\n\t" + "movsb\n" + "2:" + : "=&c" (d0), "=&D" (d1), "=&S" (d2) + :"0" (n/4), "q" (n),"1" ((long) to),"2" ((long) from) + : "memory"); +return (to); +} + +/* Even with __builtin_ the compiler may decide to use the out of line + function. */ + +#define __HAVE_ARCH_MEMCPY 1 +extern void *__memcpy(void *to, const void *from, size_t len); +#define memcpy(dst,src,len) \ + ({ size_t __len = (len); \ + void *__ret; \ + if (__builtin_constant_p(len) && __len >= 64) \ + __ret = __memcpy((dst),(src),__len); \ + else \ + __ret = __builtin_memcpy((dst),(src),__len); \ + __ret; }) + + +#define __HAVE_ARCH_MEMSET +#define memset __builtin_memset + +#define __HAVE_ARCH_MEMMOVE +void * memmove(void * dest,const void *src,size_t count); + +/* Use C out of line version for memcmp */ +#define memcmp __builtin_memcmp +int memcmp(const void * cs,const void * ct,size_t count); + +/* out of line string functions use always C versions */ +#define strlen __builtin_strlen +size_t strlen(const char * s); + +#define strcpy __builtin_strcpy +char * strcpy(char * dest,const char *src); + +#define strcat __builtin_strcat +char * strcat(char * dest, const char * src); + +#define strcmp __builtin_strcmp +int strcmp(const char * cs,const char * ct); + +#endif /* __KERNEL__ */ + +#endif diff --git a/xen/include/xen/mm.h b/xen/include/xen/mm.h index 26721e8240..4688037deb 100644 --- a/xen/include/xen/mm.h +++ b/xen/include/xen/mm.h @@ -86,7 +86,7 @@ struct pfn_info #define PageSetSlab(page) ((void)0) #define PageClearSlab(page) ((void)0) -#define IS_XEN_HEAP_FRAME(_pfn) (page_to_phys(_pfn) < MAX_XENHEAP_ADDRESS) +#define IS_XEN_HEAP_FRAME(_pfn) (page_to_phys(_pfn) < xenheap_phys_end) #define SHARE_PFN_WITH_DOMAIN(_pfn, _dom) \ do { \ @@ -104,7 +104,7 @@ extern struct list_head free_list; extern spinlock_t free_list_lock; extern unsigned int free_pfns; extern unsigned long max_page; -void init_frametable(unsigned long nr_pages); +void init_frametable(void *frametable_vstart, unsigned long nr_pages); void add_to_domain_alloc_list(unsigned long ps, unsigned long pe); struct pfn_info *alloc_domain_page(struct domain *p); |