[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] Merge with xenppc-unstable-merge.hg.
# HG changeset patch # User kaf24@xxxxxxxxxxxxxxxxxxxx # Node ID 50aea0ec406bd03dad9da31255857e4a41f7efcc # Parent e01441c9a607d3364dc092f186e0d925a3d4d8d4 # Parent 74db626d2fcfde3e61f1f43934eddd034d64a4a9 Merge with xenppc-unstable-merge.hg. --- linux-2.6-xen-sparse/arch/ia64/dig/setup.c | 2 linux-2.6-xen-sparse/arch/ia64/kernel/setup.c | 2 linux-2.6-xen-sparse/arch/ia64/xen/hypervisor.c | 27 linux-2.6-xen-sparse/arch/x86_64/kernel/setup-xen.c | 6 linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c | 60 - linux-2.6-xen-sparse/include/asm-ia64/agp.h | 12 linux-2.6-xen-sparse/include/asm-ia64/dma-mapping.h | 20 linux-2.6-xen-sparse/include/asm-ia64/hypercall.h | 165 --- linux-2.6-xen-sparse/include/asm-ia64/hypervisor.h | 38 linux-2.6-xen-sparse/include/asm-ia64/io.h | 6 linux-2.6-xen-sparse/include/asm-ia64/machvec.h | 2 linux-2.6-xen-sparse/include/asm-ia64/maddr.h | 88 + linux-2.6-xen-sparse/include/asm-ia64/page.h | 69 - linux-2.6-xen-sparse/include/asm-ia64/pgalloc.h | 4 tools/debugger/gdb/gdbbuild | 4 tools/examples/xmexample.vti | 32 tools/libxc/ia64/xc_ia64_hvm_build.c | 13 tools/libxc/ia64/xc_ia64_linux_save.c | 2 tools/libxc/ia64/xc_ia64_stubs.c | 16 xen/arch/ia64/asm-offsets.c | 1 xen/arch/ia64/linux-xen/efi.c | 22 xen/arch/ia64/linux-xen/iosapic.c | 2 xen/arch/ia64/linux-xen/irq_ia64.c | 10 xen/arch/ia64/linux-xen/mca.c | 1 xen/arch/ia64/linux-xen/process-linux-xen.c | 5 xen/arch/ia64/linux-xen/smp.c | 4 xen/arch/ia64/linux-xen/unwind.c | 3 xen/arch/ia64/vmx/Makefile | 2 xen/arch/ia64/vmx/mmio.c | 17 xen/arch/ia64/vmx/vmmu.c | 1 xen/arch/ia64/vmx/vmx_hypercall.c | 12 xen/arch/ia64/vmx/vmx_init.c | 47 xen/arch/ia64/vmx/vmx_phy_mode.c | 3 xen/arch/ia64/vmx/vmx_process.c | 8 xen/arch/ia64/vmx/vmx_support.c | 136 +- xen/arch/ia64/vmx/vtlb.c | 101 - xen/arch/ia64/xen/acpi.c | 3 xen/arch/ia64/xen/dom0_ops.c | 5 xen/arch/ia64/xen/dom_fw.c | 967 ++++++++--------- xen/arch/ia64/xen/domain.c | 49 xen/arch/ia64/xen/faults.c | 7 xen/arch/ia64/xen/flushd.S | 11 xen/arch/ia64/xen/fw_emul.c | 165 ++- xen/arch/ia64/xen/hypercall.c | 130 +- xen/arch/ia64/xen/hyperprivop.S | 81 - xen/arch/ia64/xen/irq.c | 4 xen/arch/ia64/xen/ivt.S | 1035 ++++++++++--------- xen/arch/ia64/xen/mm.c | 7 xen/arch/ia64/xen/pcdp.c | 1 xen/arch/ia64/xen/privop.c | 4 xen/arch/ia64/xen/privop_stat.c | 113 +- xen/arch/ia64/xen/vcpu.c | 31 xen/arch/ia64/xen/vhpt.c | 18 xen/arch/ia64/xen/xen.lds.S | 8 xen/arch/ia64/xen/xenasm.S | 22 xen/arch/ia64/xen/xensetup.c | 12 xen/arch/ia64/xen/xentime.c | 4 xen/arch/x86/physdev.c | 5 xen/include/asm-ia64/config.h | 6 xen/include/asm-ia64/dom_fw.h | 56 - xen/include/asm-ia64/domain.h | 14 xen/include/asm-ia64/grant_table.h | 2 xen/include/asm-ia64/linux-xen/asm/processor.h | 8 xen/include/asm-ia64/linux-xen/linux/efi.h | 4 xen/include/asm-ia64/multicall.h | 8 xen/include/asm-ia64/perfc.h | 12 xen/include/asm-ia64/perfc_defn.h | 17 xen/include/asm-ia64/privop_stat.h | 43 xen/include/asm-ia64/uaccess.h | 18 xen/include/asm-ia64/vcpu.h | 17 xen/include/asm-ia64/vhpt.h | 2 xen/include/asm-ia64/vmx.h | 8 xen/include/asm-ia64/vmx_vcpu.h | 7 xen/include/asm-ia64/vmx_vpd.h | 10 xen/include/public/domctl.h | 7 xen/include/public/xen.h | 1 76 files changed, 2182 insertions(+), 1683 deletions(-) diff -r e01441c9a607 -r 50aea0ec406b linux-2.6-xen-sparse/arch/ia64/dig/setup.c --- a/linux-2.6-xen-sparse/arch/ia64/dig/setup.c Wed Aug 30 14:09:31 2006 -0500 +++ b/linux-2.6-xen-sparse/arch/ia64/dig/setup.c Wed Aug 30 22:36:18 2006 +0100 @@ -69,7 +69,7 @@ dig_setup (char **cmdline_p) screen_info.orig_video_isVGA = 1; /* XXX fake */ screen_info.orig_video_ega_bx = 3; /* XXX fake */ #ifdef CONFIG_XEN - if (!is_running_on_xen()) + if (!is_running_on_xen() || !is_initial_xendomain()) return; if (xen_start_info->console.dom0.info_size >= diff -r e01441c9a607 -r 50aea0ec406b linux-2.6-xen-sparse/arch/ia64/kernel/setup.c --- a/linux-2.6-xen-sparse/arch/ia64/kernel/setup.c Wed Aug 30 14:09:31 2006 -0500 +++ b/linux-2.6-xen-sparse/arch/ia64/kernel/setup.c Wed Aug 30 22:36:18 2006 +0100 @@ -560,7 +560,9 @@ setup_arch (char **cmdline_p) platform_setup(cmdline_p); paging_init(); +#ifdef CONFIG_XEN contiguous_bitmap_init(max_pfn); +#endif } /* diff -r e01441c9a607 -r 50aea0ec406b linux-2.6-xen-sparse/arch/ia64/xen/hypervisor.c --- a/linux-2.6-xen-sparse/arch/ia64/xen/hypervisor.c Wed Aug 30 14:09:31 2006 -0500 +++ b/linux-2.6-xen-sparse/arch/ia64/xen/hypervisor.c Wed Aug 30 22:36:18 2006 +0100 @@ -371,6 +371,8 @@ int int HYPERVISOR_grant_table_op(unsigned int cmd, void *uop, unsigned int count) { + __u64 va1, va2, pa1, pa2; + if (cmd == GNTTABOP_map_grant_ref) { unsigned int i; for (i = 0; i < count; i++) { @@ -378,8 +380,29 @@ HYPERVISOR_grant_table_op(unsigned int c (struct gnttab_map_grant_ref*)uop + i); } } - - return ____HYPERVISOR_grant_table_op(cmd, uop, count); + va1 = (__u64)uop & PAGE_MASK; + pa1 = pa2 = 0; + if ((REGION_NUMBER(va1) == 5) && + ((va1 - KERNEL_START) >= KERNEL_TR_PAGE_SIZE)) { + pa1 = ia64_tpa(va1); + if (cmd <= GNTTABOP_transfer) { + static uint32_t uop_size[GNTTABOP_transfer + 1] = { + sizeof(struct gnttab_map_grant_ref), + sizeof(struct gnttab_unmap_grant_ref), + sizeof(struct gnttab_setup_table), + sizeof(struct gnttab_dump_table), + sizeof(struct gnttab_transfer), + }; + va2 = (__u64)uop + (uop_size[cmd] * count) - 1; + va2 &= PAGE_MASK; + if (va1 != va2) { + /* maximum size of uop is 2pages */ + BUG_ON(va2 > va1 + PAGE_SIZE); + pa2 = ia64_tpa(va2); + } + } + } + return ____HYPERVISOR_grant_table_op(cmd, uop, count, pa1, pa2); } EXPORT_SYMBOL(HYPERVISOR_grant_table_op); diff -r e01441c9a607 -r 50aea0ec406b 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 Wed Aug 30 14:09:31 2006 -0500 +++ b/linux-2.6-xen-sparse/arch/x86_64/kernel/setup-xen.c Wed Aug 30 22:36:18 2006 +0100 @@ -846,7 +846,7 @@ void __init setup_arch(char **cmdline_p) if (!xen_feature(XENFEAT_auto_translated_physmap)) { /* Make sure we have a large enough P->M table. */ - phys_to_machine_mapping = alloc_bootmem( + phys_to_machine_mapping = alloc_bootmem_pages( end_pfn * sizeof(unsigned long)); memset(phys_to_machine_mapping, ~0, end_pfn * sizeof(unsigned long)); @@ -863,7 +863,7 @@ void __init setup_arch(char **cmdline_p) * list of frames that make up the p2m table. Used by * save/restore. */ - pfn_to_mfn_frame_list_list = alloc_bootmem(PAGE_SIZE); + pfn_to_mfn_frame_list_list = alloc_bootmem_pages(PAGE_SIZE); HYPERVISOR_shared_info->arch.pfn_to_mfn_frame_list_list = virt_to_mfn(pfn_to_mfn_frame_list_list); @@ -873,7 +873,7 @@ void __init setup_arch(char **cmdline_p) k++; BUG_ON(k>=fpp); pfn_to_mfn_frame_list[k] = - alloc_bootmem(PAGE_SIZE); + alloc_bootmem_pages(PAGE_SIZE); pfn_to_mfn_frame_list_list[k] = virt_to_mfn(pfn_to_mfn_frame_list[k]); j=0; diff -r e01441c9a607 -r 50aea0ec406b linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c --- a/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c Wed Aug 30 14:09:31 2006 -0500 +++ b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c Wed Aug 30 22:36:18 2006 +0100 @@ -193,6 +193,7 @@ static void netfront_closing(struct xenb static void end_access(int, void *); static void netif_disconnect_backend(struct netfront_info *); +static int open_netdev(struct netfront_info *); static void close_netdev(struct netfront_info *); static void netif_free(struct netfront_info *); @@ -263,15 +264,22 @@ static int __devinit netfront_probe(stru dev->dev.driver_data = info; err = talk_to_backend(dev, info); - if (err) { - xennet_sysfs_delif(info->netdev); - unregister_netdev(netdev); - free_netdev(netdev); - dev->dev.driver_data = NULL; - return err; - } + if (err) + goto fail_backend; + + err = open_netdev(info); + if (err) + goto fail_open; return 0; + + fail_open: + xennet_sysfs_delif(info->netdev); + unregister_netdev(netdev); + fail_backend: + free_netdev(netdev); + dev->dev.driver_data = NULL; + return err; } @@ -1887,27 +1895,9 @@ create_netdev(int handle, int copying_re SET_MODULE_OWNER(netdev); SET_NETDEV_DEV(netdev, &dev->dev); - err = register_netdev(netdev); - if (err) { - printk(KERN_WARNING "%s> register_netdev err=%d\n", - __FUNCTION__, err); - goto exit_free_rx; - } - - err = xennet_sysfs_addif(netdev); - if (err) { - /* This can be non-fatal: it only means no tuning parameters */ - printk(KERN_WARNING "%s> add sysfs failed err=%d\n", - __FUNCTION__, err); - } - np->netdev = netdev; - return netdev; - - exit_free_rx: - gnttab_free_grant_references(np->gref_rx_head); exit_free_tx: gnttab_free_grant_references(np->gref_tx_head); exit: @@ -1966,6 +1956,26 @@ static int __devexit netfront_remove(str return 0; } + +static int open_netdev(struct netfront_info *info) +{ + int err; + + err = register_netdev(info->netdev); + if (err) { + printk(KERN_WARNING "%s: register_netdev err=%d\n", + __FUNCTION__, err); + return err; + } + + err = xennet_sysfs_addif(info->netdev); + if (err) { + /* This can be non-fatal: it only means no tuning parameters */ + printk(KERN_WARNING "%s: add sysfs failed err=%d\n", + __FUNCTION__, err); + } + return 0; +} static void close_netdev(struct netfront_info *info) { diff -r e01441c9a607 -r 50aea0ec406b linux-2.6-xen-sparse/include/asm-ia64/agp.h --- a/linux-2.6-xen-sparse/include/asm-ia64/agp.h Wed Aug 30 14:09:31 2006 -0500 +++ b/linux-2.6-xen-sparse/include/asm-ia64/agp.h Wed Aug 30 22:36:18 2006 +0100 @@ -19,10 +19,21 @@ #define flush_agp_cache() mb() /* Convert a physical address to an address suitable for the GART. */ +#ifndef CONFIG_XEN +#define phys_to_gart(x) (x) +#define gart_to_phys(x) (x) +#else #define phys_to_gart(x) phys_to_machine_for_dma(x) #define gart_to_phys(x) machine_to_phys_for_dma(x) +#endif /* GATT allocation. Returns/accepts GATT kernel virtual address. */ +#ifndef CONFIG_XEN +#define alloc_gatt_pages(order) \ + ((char *)__get_free_pages(GFP_KERNEL, (order))) +#define free_gatt_pages(table, order) \ + free_pages((unsigned long)(table), (order)) +#else #include <asm/hypervisor.h> static inline char* alloc_gatt_pages(unsigned int order) @@ -46,5 +57,6 @@ free_gatt_pages(void* table, unsigned in xen_destroy_contiguous_region((unsigned long)table, order); free_pages((unsigned long)table, order); } +#endif /* CONFIG_XEN */ #endif /* _ASM_IA64_AGP_H */ diff -r e01441c9a607 -r 50aea0ec406b linux-2.6-xen-sparse/include/asm-ia64/dma-mapping.h --- a/linux-2.6-xen-sparse/include/asm-ia64/dma-mapping.h Wed Aug 30 14:09:31 2006 -0500 +++ b/linux-2.6-xen-sparse/include/asm-ia64/dma-mapping.h Wed Aug 30 22:36:18 2006 +0100 @@ -7,11 +7,28 @@ */ #include <linux/config.h> #include <asm/machvec.h> +#ifdef CONFIG_XEN /* Needed for arch/i386/kernel/swiotlb.c and arch/i386/kernel/pci-dma-xen.c */ #include <asm/hypervisor.h> /* Needed for arch/i386/kernel/swiotlb.c */ #include <asm-i386/mach-xen/asm/swiotlb.h> +#endif +#ifndef CONFIG_XEN +#define dma_alloc_coherent platform_dma_alloc_coherent +#define dma_alloc_noncoherent platform_dma_alloc_coherent /* coherent mem. is cheap */ +#define dma_free_coherent platform_dma_free_coherent +#define dma_free_noncoherent platform_dma_free_coherent +#define dma_map_single platform_dma_map_single +#define dma_map_sg platform_dma_map_sg +#define dma_unmap_single platform_dma_unmap_single +#define dma_unmap_sg platform_dma_unmap_sg +#define dma_sync_single_for_cpu platform_dma_sync_single_for_cpu +#define dma_sync_sg_for_cpu platform_dma_sync_sg_for_cpu +#define dma_sync_single_for_device platform_dma_sync_single_for_device +#define dma_sync_sg_for_device platform_dma_sync_sg_for_device +#define dma_mapping_error platform_dma_mapping_error +#else int dma_map_sg(struct device *hwdev, struct scatterlist *sg, int nents, enum dma_data_direction direction); void dma_unmap_sg(struct device *hwdev, struct scatterlist *sg, int nents, @@ -50,6 +67,7 @@ dma_sync_sg_for_device(struct device *de swiotlb_sync_sg_for_device(dev,sg,nelems,direction); flush_write_buffers(); } +#endif #define dma_map_page(dev, pg, off, size, dir) \ dma_map_single(dev, page_address(pg) + (off), (size), (dir)) @@ -91,6 +109,7 @@ dma_cache_sync (void *vaddr, size_t size #define dma_is_consistent(dma_handle) (1) /* all we do is coherent memory... */ +#ifdef CONFIG_XEN /* arch/i386/kernel/swiotlb.o requires */ void contiguous_bitmap_init(unsigned long end_pfn); @@ -111,5 +130,6 @@ range_straddles_page_boundary(void *p, s return (((((unsigned long)p & ~PAGE_MASK) + size) > PAGE_SIZE) && !test_bit(__pa(p) >> PAGE_SHIFT, contiguous_bitmap)); } +#endif #endif /* _ASM_IA64_DMA_MAPPING_H */ diff -r e01441c9a607 -r 50aea0ec406b linux-2.6-xen-sparse/include/asm-ia64/hypercall.h --- a/linux-2.6-xen-sparse/include/asm-ia64/hypercall.h Wed Aug 30 14:09:31 2006 -0500 +++ b/linux-2.6-xen-sparse/include/asm-ia64/hypercall.h Wed Aug 30 22:36:18 2006 +0100 @@ -51,7 +51,7 @@ "break 0x1000 ;;\n" \ "mov %0=r8 ;;\n" \ : "=r" (__res) \ - : "i" (__HYPERVISOR_##name) \ + : "J" (__HYPERVISOR_##name) \ : "r2","r8", \ "memory" ); \ (type)__res; \ @@ -66,8 +66,8 @@ "break 0x1000 ;;\n" \ "mov %0=r8 ;;\n" \ : "=r" (__res) \ - : "i" (__HYPERVISOR_##name), \ - "r" ((unsigned long)(a1)) \ + : "J" (__HYPERVISOR_##name), \ + "rI" ((unsigned long)(a1)) \ : "r14","r2","r8", \ "memory" ); \ (type)__res; \ @@ -83,9 +83,9 @@ "break 0x1000 ;;\n" \ "mov %0=r8 ;;\n" \ : "=r" (__res) \ - : "i" (__HYPERVISOR_##name), \ - "r" ((unsigned long)(a1)), \ - "r" ((unsigned long)(a2)) \ + : "J" (__HYPERVISOR_##name), \ + "rI" ((unsigned long)(a1)), \ + "rI" ((unsigned long)(a2)) \ : "r14","r15","r2","r8", \ "memory" ); \ (type)__res; \ @@ -102,10 +102,10 @@ "break 0x1000 ;;\n" \ "mov %0=r8 ;;\n" \ : "=r" (__res) \ - : "i" (__HYPERVISOR_##name), \ - "r" ((unsigned long)(a1)), \ - "r" ((unsigned long)(a2)), \ - "r" ((unsigned long)(a3)) \ + : "J" (__HYPERVISOR_##name), \ + "rI" ((unsigned long)(a1)), \ + "rI" ((unsigned long)(a2)), \ + "rI" ((unsigned long)(a3)) \ : "r14","r15","r16","r2","r8", \ "memory" ); \ (type)__res; \ @@ -123,11 +123,11 @@ "break 0x1000 ;;\n" \ "mov %0=r8 ;;\n" \ : "=r" (__res) \ - : "i" (__HYPERVISOR_##name), \ - "r" ((unsigned long)(a1)), \ - "r" ((unsigned long)(a2)), \ - "r" ((unsigned long)(a3)), \ - "r" ((unsigned long)(a4)) \ + : "J" (__HYPERVISOR_##name), \ + "rI" ((unsigned long)(a1)), \ + "rI" ((unsigned long)(a2)), \ + "rI" ((unsigned long)(a3)), \ + "rI" ((unsigned long)(a4)) \ : "r14","r15","r16","r2","r8", \ "r17","memory" ); \ (type)__res; \ @@ -146,12 +146,12 @@ "break 0x1000 ;;\n" \ "mov %0=r8 ;;\n" \ : "=r" (__res) \ - : "i" (__HYPERVISOR_##name), \ - "r" ((unsigned long)(a1)), \ - "r" ((unsigned long)(a2)), \ - "r" ((unsigned long)(a3)), \ - "r" ((unsigned long)(a4)), \ - "r" ((unsigned long)(a5)) \ + : "J" (__HYPERVISOR_##name), \ + "rI" ((unsigned long)(a1)), \ + "rI" ((unsigned long)(a2)), \ + "rI" ((unsigned long)(a3)), \ + "rI" ((unsigned long)(a4)), \ + "rI" ((unsigned long)(a5)) \ : "r14","r15","r16","r2","r8", \ "r17","r18","memory" ); \ (type)__res; \ @@ -275,9 +275,10 @@ HYPERVISOR_physdev_op( //XXX __HYPERVISOR_grant_table_op is used for this hypercall constant. static inline int ____HYPERVISOR_grant_table_op( - unsigned int cmd, void *uop, unsigned int count) -{ - return _hypercall3(int, grant_table_op, cmd, uop, count); + unsigned int cmd, void *uop, unsigned int count, + unsigned long pa1, unsigned long pa2) +{ + return _hypercall5(int, grant_table_op, cmd, uop, count, pa1, pa2); } int HYPERVISOR_grant_table_op(unsigned int cmd, void *uop, unsigned int count); @@ -290,6 +291,13 @@ HYPERVISOR_vcpu_op( } extern int HYPERVISOR_suspend(unsigned long srec); + +static inline unsigned long +HYPERVISOR_hvm_op( + int cmd, void *arg) +{ + return _hypercall2(unsigned long, hvm_op, cmd, arg); +} static inline int HYPERVISOR_callback_op( @@ -307,99 +315,15 @@ static inline void exit_idle(void) {} }) #include <linux/err.h> +#ifdef CONFIG_XEN #include <asm/xen/privop.h> - -#define _hypercall_imm1(type, name, imm, a1) \ -({ \ - long __res; \ - __asm__ __volatile__ (";;\n" \ - "mov r14=%2\n" \ - "mov r15=%3\n" \ - "mov r2=%1\n" \ - "break 0x1000 ;;\n" \ - "mov %0=r8 ;;\n" \ - : "=r" (__res) \ - : "i" (__HYPERVISOR_##name), \ - "i" (imm), \ - "r" ((unsigned long)(a1)) \ - : "r14","r15","r2","r8", \ - "memory" ); \ - (type)__res; \ -}) - -#define _hypercall_imm2(type, name, imm, a1, a2) \ -({ \ - long __res; \ - __asm__ __volatile__ (";;\n" \ - "mov r14=%2\n" \ - "mov r15=%3\n" \ - "mov r16=%4\n" \ - "mov r2=%1\n" \ - "break 0x1000 ;;\n" \ - "mov %0=r8 ;;\n" \ - : "=r" (__res) \ - : "i" (__HYPERVISOR_##name), \ - "i" (imm), \ - "r" ((unsigned long)(a1)), \ - "r" ((unsigned long)(a2)) \ - : "r14","r15","r16","r2","r8", \ - "memory" ); \ - (type)__res; \ -}) - -#define _hypercall_imm3(type, name, imm, a1, a2, a3) \ -({ \ - long __res; \ - __asm__ __volatile__ (";;\n" \ - "mov r14=%2\n" \ - "mov r15=%3\n" \ - "mov r16=%4\n" \ - "mov r17=%5\n" \ - "mov r2=%1\n" \ - "break 0x1000 ;;\n" \ - "mov %0=r8 ;;\n" \ - : "=r" (__res) \ - : "i" (__HYPERVISOR_##name), \ - "i" (imm), \ - "r" ((unsigned long)(a1)), \ - "r" ((unsigned long)(a2)), \ - "r" ((unsigned long)(a3)) \ - : "r14","r15","r16","r17", \ - "r2","r8", \ - "memory" ); \ - (type)__res; \ -}) - -#define _hypercall_imm4(type, name, imm, a1, a2, a3, a4) \ -({ \ - long __res; \ - __asm__ __volatile__ (";;\n" \ - "mov r14=%2\n" \ - "mov r15=%3\n" \ - "mov r16=%4\n" \ - "mov r17=%5\n" \ - "mov r18=%6\n" \ - "mov r2=%1\n" \ - "break 0x1000 ;;\n" \ - "mov %0=r8 ;;\n" \ - : "=r" (__res) \ - : "i" (__HYPERVISOR_##name), \ - "i" (imm), \ - "r" ((unsigned long)(a1)), \ - "r" ((unsigned long)(a2)), \ - "r" ((unsigned long)(a3)), \ - "r" ((unsigned long)(a4)) \ - : "r14","r15","r16","r17","r18", \ - "r2","r8", \ - "memory" ); \ - (type)__res; \ -}) +#endif /* CONFIG_XEN */ static inline unsigned long __HYPERVISOR_ioremap(unsigned long ioaddr, unsigned long size) { - return _hypercall_imm2(unsigned long, ia64_dom0vp_op, - IA64_DOM0VP_ioremap, ioaddr, size); + return _hypercall3(unsigned long, ia64_dom0vp_op, + IA64_DOM0VP_ioremap, ioaddr, size); } static inline unsigned long @@ -421,8 +345,8 @@ static inline unsigned long static inline unsigned long __HYPERVISOR_phystomach(unsigned long gpfn) { - return _hypercall_imm1(unsigned long, ia64_dom0vp_op, - IA64_DOM0VP_phystomach, gpfn); + return _hypercall2(unsigned long, ia64_dom0vp_op, + IA64_DOM0VP_phystomach, gpfn); } static inline unsigned long @@ -438,8 +362,8 @@ static inline unsigned long static inline unsigned long __HYPERVISOR_machtophys(unsigned long mfn) { - return _hypercall_imm1(unsigned long, ia64_dom0vp_op, - IA64_DOM0VP_machtophys, mfn); + return _hypercall2(unsigned long, ia64_dom0vp_op, + IA64_DOM0VP_machtophys, mfn); } static inline unsigned long @@ -455,8 +379,8 @@ static inline unsigned long static inline unsigned long __HYPERVISOR_zap_physmap(unsigned long gpfn, unsigned int extent_order) { - return _hypercall_imm2(unsigned long, ia64_dom0vp_op, - IA64_DOM0VP_zap_physmap, gpfn, extent_order); + return _hypercall3(unsigned long, ia64_dom0vp_op, + IA64_DOM0VP_zap_physmap, gpfn, extent_order); } static inline unsigned long @@ -473,9 +397,8 @@ __HYPERVISOR_add_physmap(unsigned long g __HYPERVISOR_add_physmap(unsigned long gpfn, unsigned long mfn, unsigned long flags, domid_t domid) { - return _hypercall_imm4(unsigned long, ia64_dom0vp_op, - IA64_DOM0VP_add_physmap, gpfn, mfn, flags, - domid); + return _hypercall5(unsigned long, ia64_dom0vp_op, + IA64_DOM0VP_add_physmap, gpfn, mfn, flags, domid); } static inline unsigned long diff -r e01441c9a607 -r 50aea0ec406b linux-2.6-xen-sparse/include/asm-ia64/hypervisor.h --- a/linux-2.6-xen-sparse/include/asm-ia64/hypervisor.h Wed Aug 30 14:09:31 2006 -0500 +++ b/linux-2.6-xen-sparse/include/asm-ia64/hypervisor.h Wed Aug 30 22:36:18 2006 +0100 @@ -33,7 +33,7 @@ #ifndef __HYPERVISOR_H__ #define __HYPERVISOR_H__ -#ifndef CONFIG_XEN +#if !defined(CONFIG_XEN) && !defined(CONFIG_VMX_GUEST) #define is_running_on_xen() (0) #define HYPERVISOR_ioremap(offset, size) (offset) #else @@ -41,7 +41,7 @@ extern int running_on_xen; #define is_running_on_xen() (running_on_xen) #endif -#ifdef CONFIG_XEN +#if defined(CONFIG_XEN) || defined(CONFIG_VMX_GUEST) #include <linux/config.h> #include <linux/types.h> #include <linux/kernel.h> @@ -59,10 +59,9 @@ extern shared_info_t *HYPERVISOR_shared_ extern shared_info_t *HYPERVISOR_shared_info; extern start_info_t *xen_start_info; -#define is_initial_xendomain() (xen_start_info->flags & SIF_INITDOMAIN) - void force_evtchn_callback(void); +#ifndef CONFIG_VMX_GUEST /* Turn jiffies into Xen system time. XXX Implement me. */ #define jiffies_to_st(j) 0 @@ -145,10 +144,14 @@ int privcmd_mmap(struct file * file, str #define scrub_pages(_p,_n) ((void)0) #endif #define pte_mfn(_x) pte_pfn(_x) -#define __pte_ma(_x) ((pte_t) {(_x)}) #define phys_to_machine_mapping_valid(_x) (1) -#define pfn_pte_ma(_x,_y) __pte_ma(0) - + +#endif /* !CONFIG_VMX_GUEST */ + +#define __pte_ma(_x) ((pte_t) {(_x)}) /* unmodified use */ +#define pfn_pte_ma(_x,_y) __pte_ma(0) /* unmodified use */ + +#ifndef CONFIG_VMX_GUEST int __xen_create_contiguous_region(unsigned long vstart, unsigned int order, unsigned int address_bits); static inline int xen_create_contiguous_region(unsigned long vstart, @@ -170,6 +173,8 @@ xen_destroy_contiguous_region(unsigned l __xen_destroy_contiguous_region(vstart, order); } +#endif /* !CONFIG_VMX_GUEST */ + // for netfront.c, netback.c #define MULTI_UVMFLAGS_INDEX 0 //XXX any value @@ -180,12 +185,29 @@ MULTI_update_va_mapping( { mcl->op = __HYPERVISOR_update_va_mapping; mcl->result = 0; +} + +static inline void +MULTI_grant_table_op(multicall_entry_t *mcl, unsigned int cmd, + void *uop, unsigned int count) +{ + mcl->op = __HYPERVISOR_grant_table_op; + mcl->args[0] = cmd; + mcl->args[1] = (unsigned long)uop; + mcl->args[2] = count; } // for debug asmlinkage int xprintk(const char *fmt, ...); #define xprintd(fmt, ...) xprintk("%s:%d " fmt, __func__, __LINE__, \ ##__VA_ARGS__) -#endif /* CONFIG_XEN */ + +#endif /* CONFIG_XEN || CONFIG_VMX_GUEST */ + +#ifdef CONFIG_XEN_PRIVILEGED_GUEST +#define is_initial_xendomain() (xen_start_info->flags & SIF_INITDOMAIN) +#else +#define is_initial_xendomain() 0 +#endif #endif /* __HYPERVISOR_H__ */ diff -r e01441c9a607 -r 50aea0ec406b linux-2.6-xen-sparse/include/asm-ia64/io.h --- a/linux-2.6-xen-sparse/include/asm-ia64/io.h Wed Aug 30 14:09:31 2006 -0500 +++ b/linux-2.6-xen-sparse/include/asm-ia64/io.h Wed Aug 30 22:36:18 2006 +0100 @@ -97,6 +97,11 @@ extern int valid_mmap_phys_addr_range (u * The following two macros are deprecated and scheduled for removal. * Please use the PCI-DMA interface defined in <asm/pci.h> instead. */ +#ifndef CONFIG_XEN +#define bus_to_virt phys_to_virt +#define virt_to_bus virt_to_phys +#define page_to_bus page_to_phys +#else #define bus_to_virt(bus) \ phys_to_virt(machine_to_phys_for_dma(bus)) #define virt_to_bus(virt) \ @@ -124,6 +129,7 @@ extern int valid_mmap_phys_addr_range (u (((bvec_to_bus((vec1)) + (vec1)->bv_len) == bvec_to_bus((vec2))) && \ ((bvec_to_pseudophys((vec1)) + (vec1)->bv_len) == \ bvec_to_pseudophys((vec2)))) +#endif /* CONFIG_XEN */ # endif /* KERNEL */ diff -r e01441c9a607 -r 50aea0ec406b linux-2.6-xen-sparse/include/asm-ia64/machvec.h --- a/linux-2.6-xen-sparse/include/asm-ia64/machvec.h Wed Aug 30 14:09:31 2006 -0500 +++ b/linux-2.6-xen-sparse/include/asm-ia64/machvec.h Wed Aug 30 22:36:18 2006 +0100 @@ -247,6 +247,7 @@ extern void machvec_init (const char *na # error Unknown configuration. Update asm-ia64/machvec.h. # endif /* CONFIG_IA64_GENERIC */ +#ifdef CONFIG_XEN # define platform_dma_map_sg dma_map_sg # define platform_dma_unmap_sg dma_unmap_sg # define platform_dma_mapping_error dma_mapping_error @@ -259,6 +260,7 @@ extern void machvec_init (const char *na dma_sync_single_for_cpu # define platform_dma_sync_single_for_device \ dma_sync_single_for_device +#endif /* * Declare default routines which aren't declared anywhere else: diff -r e01441c9a607 -r 50aea0ec406b linux-2.6-xen-sparse/include/asm-ia64/page.h --- a/linux-2.6-xen-sparse/include/asm-ia64/page.h Wed Aug 30 14:09:31 2006 -0500 +++ b/linux-2.6-xen-sparse/include/asm-ia64/page.h Wed Aug 30 22:36:18 2006 +0100 @@ -117,6 +117,9 @@ extern unsigned long max_low_pfn; # define pfn_to_page(pfn) (vmem_map + (pfn)) #endif +#ifndef CONFIG_XEN +#define page_to_phys(page) (page_to_pfn(page) << PAGE_SHIFT) +#endif #define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT) #define pfn_to_kaddr(pfn) __va((pfn) << PAGE_SHIFT) @@ -221,12 +224,9 @@ get_order (unsigned long size) #ifndef __ASSEMBLY__ #ifdef CONFIG_XEN -#define INVALID_P2M_ENTRY (~0UL) - #include <linux/kernel.h> #include <asm/hypervisor.h> #include <xen/features.h> // to compile netback, netfront -typedef unsigned long maddr_t; // to compile netback, netfront /* * XXX hack! @@ -265,68 +265,7 @@ extern struct address_space xen_ia64_for }) #define HAVE_ARCH_FREE_PAGE -/* XXX xen page size != page size */ - -static inline unsigned long -pfn_to_mfn_for_dma(unsigned long pfn) -{ - unsigned long mfn; - mfn = HYPERVISOR_phystomach(pfn); - BUG_ON(mfn == 0); // XXX - BUG_ON(mfn == INVALID_P2M_ENTRY); // XXX - BUG_ON(mfn == INVALID_MFN); - return mfn; -} - -static inline unsigned long -phys_to_machine_for_dma(unsigned long phys) -{ - unsigned long machine = - pfn_to_mfn_for_dma(phys >> PAGE_SHIFT) << PAGE_SHIFT; - machine |= (phys & ~PAGE_MASK); - return machine; -} - -static inline unsigned long -mfn_to_pfn_for_dma(unsigned long mfn) -{ - unsigned long pfn; - pfn = HYPERVISOR_machtophys(mfn); - BUG_ON(pfn == 0); - //BUG_ON(pfn == INVALID_M2P_ENTRY); - return pfn; -} - -static inline unsigned long -machine_to_phys_for_dma(unsigned long machine) -{ - unsigned long phys = - mfn_to_pfn_for_dma(machine >> PAGE_SHIFT) << PAGE_SHIFT; - phys |= (machine & ~PAGE_MASK); - return phys; -} - -#define set_phys_to_machine(pfn, mfn) do { } while (0) -#define xen_machphys_update(mfn, pfn) do { } while (0) - -/* XXX to compile set_phys_to_machine(vaddr, FOREIGN_FRAME(m)) */ -#define FOREIGN_FRAME(m) (INVALID_P2M_ENTRY) - -#define mfn_to_pfn(mfn) (mfn) -#define mfn_to_virt(mfn) (__va((mfn) << PAGE_SHIFT)) -#define pfn_to_mfn(pfn) (pfn) -#define virt_to_mfn(virt) (__pa(virt) >> PAGE_SHIFT) -#define virt_to_machine(virt) __pa(virt) // for tpmfront.c - -static inline unsigned long -mfn_to_local_pfn(unsigned long mfn) -{ - extern unsigned long max_mapnr; - unsigned long pfn = mfn_to_pfn_for_dma(mfn); - if (!pfn_valid(pfn)) - return INVALID_P2M_ENTRY; - return pfn; -} +#include <asm/maddr.h> #endif /* CONFIG_XEN */ #endif /* __ASSEMBLY__ */ diff -r e01441c9a607 -r 50aea0ec406b linux-2.6-xen-sparse/include/asm-ia64/pgalloc.h --- a/linux-2.6-xen-sparse/include/asm-ia64/pgalloc.h Wed Aug 30 14:09:31 2006 -0500 +++ b/linux-2.6-xen-sparse/include/asm-ia64/pgalloc.h Wed Aug 30 22:36:18 2006 +0100 @@ -126,7 +126,11 @@ static inline void static inline void pmd_populate(struct mm_struct *mm, pmd_t * pmd_entry, struct page *pte) { +#ifndef CONFIG_XEN + pmd_val(*pmd_entry) = page_to_phys(pte); +#else pmd_val(*pmd_entry) = page_to_pseudophys(pte); +#endif } static inline void diff -r e01441c9a607 -r 50aea0ec406b tools/debugger/gdb/gdbbuild --- a/tools/debugger/gdb/gdbbuild Wed Aug 30 14:09:31 2006 -0500 +++ b/tools/debugger/gdb/gdbbuild Wed Aug 30 22:36:18 2006 +0100 @@ -18,7 +18,7 @@ if [ "$MAKE" ]; then if [ "$MAKE" ]; then $MAKE elif which gmake ; then - gmake -j4 + gmake -j4 CFLAGS=-D__XEN_TOOLS__ else - make -j4 + make -j4 CFLAGS=-D__XEN_TOOLS__ fi diff -r e01441c9a607 -r 50aea0ec406b tools/examples/xmexample.vti --- a/tools/examples/xmexample.vti Wed Aug 30 14:09:31 2006 -0500 +++ b/tools/examples/xmexample.vti Wed Aug 30 22:36:18 2006 +0100 @@ -37,11 +37,9 @@ name = "ExampleVTIDomain" # Optionally define mac and/or bridge for the network interfaces. # Random MACs are assigned if not given. -#vif = [ 'type=ioemu, mac=00:16:3e:00:00:11, bridge=xenbr0' ] +#vif = [ 'type=ioemu, mac=00:16:3e:00:00:11, bridge=xenbr0, model=ne2k_pci' ] # type=ioemu specify the NIC is an ioemu device not netfront vif = [ 'type=ioemu, bridge=xenbr0' ] -# for multiple NICs in device model, 3 in this example -#vif = [ 'type=ioemu, bridge=xenbr0', 'type=ioemu', 'type=ioemu'] #---------------------------------------------------------------------------- # Define the disk devices you want the domain to have access to, and @@ -51,7 +49,7 @@ vif = [ 'type=ioemu, bridge=xenbr0' ] # and MODE is r for read-only, w for read-write. #disk = [ 'phy:hda1,hda1,r' ] -disk = [ 'file:/var/images/xenia64.img,ioemu:hda,w' ] +disk = [ 'file:/var/images/xenia64.img,hda,w', ',hdc:cdrom,r' ] #---------------------------------------------------------------------------- # Set according to whether you want the domain restarted when it exits. @@ -65,13 +63,6 @@ disk = [ 'file:/var/images/xenia64.img,i # New stuff device_model = '/usr/' + arch_libdir + '/xen/bin/qemu-dm' - -# Advanced users only. Don't touch if you don't know what you're doing -memmap = '/usr/lib/xen/boot/mem-map.sxp' - -#----------------------------------------------------------------------------- -# Disk image for -#cdrom= #----------------------------------------------------------------------------- # boot on floppy (a), hard disk (c) or CD-ROM (d) @@ -91,8 +82,17 @@ vnc=0 vnc=0 #---------------------------------------------------------------------------- -# enable spawning vncviewer(only valid when vnc=1), default = 1 -vncviewer=0 +# set VNC display number, default = domid +#vncdisplay=1 + +#---------------------------------------------------------------------------- +# try to find an unused port for the VNC server, default = 1 +#vncunused=1 + +#---------------------------------------------------------------------------- +# enable spawning vncviewer for domain's console +# (only valid when vnc=1), default = 0 +#vncconsole=0 #---------------------------------------------------------------------------- # no graphics, use serial port @@ -108,14 +108,12 @@ serial='pty' serial='pty' #----------------------------------------------------------------------------- -# enable audio support -#enable-audio=1 - +# enable sound card support, [sb16|es1370|all|..,..], default none +#soundhw='sb16' #----------------------------------------------------------------------------- # set the real time clock to local time [default=0 i.e. set to utc] #localtime=1 - #----------------------------------------------------------------------------- # start in full screen diff -r e01441c9a607 -r 50aea0ec406b tools/libxc/ia64/xc_ia64_hvm_build.c --- a/tools/libxc/ia64/xc_ia64_hvm_build.c Wed Aug 30 14:09:31 2006 -0500 +++ b/tools/libxc/ia64/xc_ia64_hvm_build.c Wed Aug 30 22:36:18 2006 +0100 @@ -553,7 +553,6 @@ setup_guest(int xc_handle, uint32_t dom, { unsigned long page_array[2]; shared_iopage_t *sp; - int i; unsigned long dom_memsize = (memsize << 20); DECLARE_DOMCTL; @@ -604,18 +603,6 @@ setup_guest(int xc_handle, uint32_t dom, goto error_out; memset(sp, 0, PAGE_SIZE); - - for (i = 0; i < vcpus; i++) { - uint32_t vp_eport; - - vp_eport = xc_evtchn_alloc_unbound(xc_handle, dom, 0); - if (vp_eport < 0) { - DPRINTF("Couldn't get unbound port from VMX guest.\n"); - goto error_out; - } - sp->vcpu_iodata[i].vp_eport = vp_eport; - } - munmap(sp, PAGE_SIZE); return 0; diff -r e01441c9a607 -r 50aea0ec406b tools/libxc/ia64/xc_ia64_linux_save.c --- a/tools/libxc/ia64/xc_ia64_linux_save.c Wed Aug 30 14:09:31 2006 -0500 +++ b/tools/libxc/ia64/xc_ia64_linux_save.c Wed Aug 30 22:36:18 2006 +0100 @@ -79,7 +79,7 @@ static int xc_ia64_shadow_control(int xc } return xc_shadow_control(xc_handle, domid, sop, - dirty_bitmap, pages, stats); + dirty_bitmap, pages, NULL, 0, stats); } static inline ssize_t diff -r e01441c9a607 -r 50aea0ec406b tools/libxc/ia64/xc_ia64_stubs.c --- a/tools/libxc/ia64/xc_ia64_stubs.c Wed Aug 30 14:09:31 2006 -0500 +++ b/tools/libxc/ia64/xc_ia64_stubs.c Wed Aug 30 22:36:18 2006 +0100 @@ -36,7 +36,6 @@ xc_ia64_get_pfn_list(int xc_handle, uint struct xen_domctl domctl; int num_pfns,ret; unsigned int __start_page, __nr_pages; - unsigned long max_pfns; xen_pfn_t *__pfn_buf; __start_page = start_page; @@ -44,27 +43,22 @@ xc_ia64_get_pfn_list(int xc_handle, uint __pfn_buf = pfn_buf; while (__nr_pages) { - max_pfns = ((unsigned long)__start_page << 32) | __nr_pages; domctl.cmd = XEN_DOMCTL_getmemlist; - domctl.domain = (domid_t)domid; - domctl.u.getmemlist.max_pfns = max_pfns; + domctl.domain = (domid_t)domid; + domctl.u.getmemlist.max_pfns = __nr_pages; + domctl.u.getmemlist.start_pfn =__start_page; domctl.u.getmemlist.num_pfns = 0; set_xen_guest_handle(domctl.u.getmemlist.buffer, __pfn_buf); - if ((max_pfns != -1UL) - && mlock(__pfn_buf, __nr_pages * sizeof(xen_pfn_t)) != 0) { + if (mlock(__pfn_buf, __nr_pages * sizeof(xen_pfn_t)) != 0) { PERROR("Could not lock pfn list buffer"); return -1; } ret = do_domctl(xc_handle, &domctl); - if (max_pfns != -1UL) - (void)munlock(__pfn_buf, __nr_pages * sizeof(xen_pfn_t)); + (void)munlock(__pfn_buf, __nr_pages * sizeof(xen_pfn_t)); - if (max_pfns == -1UL) - return 0; - num_pfns = domctl.u.getmemlist.num_pfns; __start_page += num_pfns; __nr_pages -= num_pfns; diff -r e01441c9a607 -r 50aea0ec406b xen/arch/ia64/asm-offsets.c --- a/xen/arch/ia64/asm-offsets.c Wed Aug 30 14:09:31 2006 -0500 +++ b/xen/arch/ia64/asm-offsets.c Wed Aug 30 22:36:18 2006 +0100 @@ -31,7 +31,6 @@ void foo(void) DEFINE(IA64_SWITCH_STACK_SIZE, sizeof (struct switch_stack)); DEFINE(IA64_CPU_SIZE, sizeof (struct cpuinfo_ia64)); DEFINE(UNW_FRAME_INFO_SIZE, sizeof (struct unw_frame_info)); - DEFINE(SHARED_INFO_SIZE, sizeof (struct shared_info)); DEFINE(MAPPED_REGS_T_SIZE, sizeof (mapped_regs_t)); BLANK(); diff -r e01441c9a607 -r 50aea0ec406b xen/arch/ia64/linux-xen/efi.c --- a/xen/arch/ia64/linux-xen/efi.c Wed Aug 30 14:09:31 2006 -0500 +++ b/xen/arch/ia64/linux-xen/efi.c Wed Aug 30 22:36:18 2006 +0100 @@ -291,28 +291,6 @@ efi_memmap_walk_uc (efi_freemem_callback { walk(callback, arg, EFI_MEMORY_UC); } - -#ifdef XEN -void -efi_memmap_walk_type(u32 type, efi_walk_type_callback_t callback, void *arg) -{ - void *efi_map_start, *efi_map_end, *p; - efi_memory_desc_t *md; - u64 efi_desc_size; - - efi_map_start = __va(ia64_boot_param->efi_memmap); - efi_map_end = efi_map_start + ia64_boot_param->efi_memmap_size; - efi_desc_size = ia64_boot_param->efi_memdesc_size; - - for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) { - md = p; - if (md->type == type) { - if ((*callback)(md, arg) < 0) - return; - } - } -} -#endif /* * Look for the PAL_CODE region reported by EFI and maps it using an diff -r e01441c9a607 -r 50aea0ec406b xen/arch/ia64/linux-xen/iosapic.c --- a/xen/arch/ia64/linux-xen/iosapic.c Wed Aug 30 14:09:31 2006 -0500 +++ b/xen/arch/ia64/linux-xen/iosapic.c Wed Aug 30 22:36:18 2006 +0100 @@ -77,6 +77,8 @@ #include <linux/list.h> #ifndef XEN #include <linux/pci.h> +#else +#include <xen/errno.h> #endif #include <linux/smp.h> #include <linux/smp_lock.h> diff -r e01441c9a607 -r 50aea0ec406b xen/arch/ia64/linux-xen/irq_ia64.c --- a/xen/arch/ia64/linux-xen/irq_ia64.c Wed Aug 30 14:09:31 2006 -0500 +++ b/xen/arch/ia64/linux-xen/irq_ia64.c Wed Aug 30 22:36:18 2006 +0100 @@ -40,6 +40,10 @@ #include <asm/pgtable.h> #include <asm/system.h> +#ifdef XEN +#include <xen/perfc.h> +#endif + #ifdef CONFIG_PERFMON # include <asm/perfmon.h> #endif @@ -108,6 +112,9 @@ ia64_handle_irq (ia64_vector vector, str { unsigned long saved_tpr; +#ifdef XEN + perfc_incrc(irqs); +#endif #if IRQ_DEBUG #ifdef XEN xen_debug_irq(vector, regs); @@ -290,8 +297,5 @@ ia64_send_ipi (int cpu, int vector, int ipi_data = (delivery_mode << 8) | (vector & 0xff); ipi_addr = ipi_base_addr + ((phys_cpu_id << 4) | ((redirect & 1) << 3)); -#ifdef XEN - //printf ("send_ipi to %d (%x)\n", cpu, phys_cpu_id); -#endif writeq(ipi_data, ipi_addr); } diff -r e01441c9a607 -r 50aea0ec406b xen/arch/ia64/linux-xen/mca.c --- a/xen/arch/ia64/linux-xen/mca.c Wed Aug 30 14:09:31 2006 -0500 +++ b/xen/arch/ia64/linux-xen/mca.c Wed Aug 30 22:36:18 2006 +0100 @@ -79,6 +79,7 @@ #ifdef XEN #include <xen/symbols.h> +#include <xen/mm.h> #endif #if defined(IA64_MCA_DEBUG_INFO) diff -r e01441c9a607 -r 50aea0ec406b xen/arch/ia64/linux-xen/process-linux-xen.c --- a/xen/arch/ia64/linux-xen/process-linux-xen.c Wed Aug 30 14:09:31 2006 -0500 +++ b/xen/arch/ia64/linux-xen/process-linux-xen.c Wed Aug 30 22:36:18 2006 +0100 @@ -10,6 +10,7 @@ #include <xen/lib.h> #include <xen/symbols.h> #include <xen/smp.h> +#include <xen/sched.h> #include <asm/uaccess.h> #include <asm/processor.h> #include <asm/ptrace.h> @@ -166,6 +167,7 @@ show_regs (struct pt_regs *regs) printk("r26 : %016lx r27 : %016lx r28 : %016lx\n", regs->r26, regs->r27, regs->r28); printk("r29 : %016lx r30 : %016lx r31 : %016lx\n", regs->r29, regs->r30, regs->r31); +#ifndef XEN if (user_mode(regs)) { /* print the stacked registers */ unsigned long val, *bsp, ndirty; @@ -180,6 +182,7 @@ show_regs (struct pt_regs *regs) ((i == sof - 1) || (i % 3) == 2) ? "\n" : " "); } } else +#endif show_stack(NULL, NULL); } @@ -807,6 +810,7 @@ get_wchan (struct task_struct *p) } while (count++ < 16); return 0; } +#endif // !XEN void cpu_halt (void) @@ -831,6 +835,7 @@ cpu_halt (void) ia64_pal_halt(min_power_state); } +#ifndef XEN void machine_restart (char *restart_cmd) { diff -r e01441c9a607 -r 50aea0ec406b xen/arch/ia64/linux-xen/smp.c --- a/xen/arch/ia64/linux-xen/smp.c Wed Aug 30 14:09:31 2006 -0500 +++ b/xen/arch/ia64/linux-xen/smp.c Wed Aug 30 22:36:18 2006 +0100 @@ -48,6 +48,7 @@ #include <asm/unistd.h> #include <asm/mca.h> #ifdef XEN +#include <xen/errno.h> #include <asm/vhpt.h> #include <asm/hw_irq.h> #endif @@ -146,6 +147,9 @@ handle_IPI (int irq, void *dev_id, struc unsigned long *pending_ipis = &__ia64_per_cpu_var(ipi_operation); unsigned long ops; +#ifdef XEN + perfc_incrc(ipis); +#endif mb(); /* Order interrupt and bit testing. */ while ((ops = xchg(pending_ipis, 0)) != 0) { mb(); /* Order bit clearing and data access. */ diff -r e01441c9a607 -r 50aea0ec406b xen/arch/ia64/linux-xen/unwind.c --- a/xen/arch/ia64/linux-xen/unwind.c Wed Aug 30 14:09:31 2006 -0500 +++ b/xen/arch/ia64/linux-xen/unwind.c Wed Aug 30 22:36:18 2006 +0100 @@ -33,6 +33,7 @@ #include <xen/sched.h> #include <xen/xmalloc.h> #include <xen/spinlock.h> +#include <xen/errno.h> // work around #ifdef CONFIG_SMP @@ -2315,6 +2316,7 @@ unw_init (void) __start_unwind, __end_unwind); } +#ifndef XEN /* * DEPRECATED DEPRECATED DEPRECATED DEPRECATED DEPRECATED DEPRECATED DEPRECATED * @@ -2353,3 +2355,4 @@ sys_getunwind (void __user *buf, size_t return -EFAULT; return unw.gate_table_size; } +#endif diff -r e01441c9a607 -r 50aea0ec406b xen/arch/ia64/vmx/Makefile --- a/xen/arch/ia64/vmx/Makefile Wed Aug 30 14:09:31 2006 -0500 +++ b/xen/arch/ia64/vmx/Makefile Wed Aug 30 22:36:18 2006 +0100 @@ -1,5 +1,5 @@ obj-y += hvm_vioapic.o obj-y += hvm_vioapic.o -obj-y += mm.o +#obj-y += mm.o obj-y += mmio.o obj-y += pal_emul.o obj-y += vlsapic.o diff -r e01441c9a607 -r 50aea0ec406b xen/arch/ia64/vmx/mmio.c --- a/xen/arch/ia64/vmx/mmio.c Wed Aug 30 14:09:31 2006 -0500 +++ b/xen/arch/ia64/vmx/mmio.c Wed Aug 30 22:36:18 2006 +0100 @@ -22,6 +22,7 @@ */ #include <linux/sched.h> +#include <xen/mm.h> #include <asm/tlb.h> #include <asm/vmx_mm_def.h> #include <asm/gcc_intrin.h> @@ -30,7 +31,6 @@ #include <asm/bundle.h> #include <asm/types.h> #include <public/hvm/ioreq.h> -#include <asm/mm.h> #include <asm/vmx.h> #include <public/event_channel.h> #include <public/xen.h> @@ -155,10 +155,9 @@ static void low_mmio_access(VCPU *vcpu, p->type = 1; p->df = 0; - set_bit(ARCH_VMX_IO_WAIT, &v->arch.arch_vmx.flags); - p->state = STATE_IOREQ_READY; - evtchn_send(iopacket_port(v)); - vmx_wait_io(); + p->io_count++; + + vmx_send_assist_req(v); if(dir==IOREQ_READ){ //read *val=p->u.data; } @@ -187,11 +186,9 @@ static void legacy_io_access(VCPU *vcpu, p->type = 0; p->df = 0; - set_bit(ARCH_VMX_IO_WAIT, &v->arch.arch_vmx.flags); - p->state = STATE_IOREQ_READY; - evtchn_send(iopacket_port(v)); - - vmx_wait_io(); + p->io_count++; + + vmx_send_assist_req(v); if(dir==IOREQ_READ){ //read *val=p->u.data; } diff -r e01441c9a607 -r 50aea0ec406b xen/arch/ia64/vmx/vmmu.c --- a/xen/arch/ia64/vmx/vmmu.c Wed Aug 30 14:09:31 2006 -0500 +++ b/xen/arch/ia64/vmx/vmmu.c Wed Aug 30 22:36:18 2006 +0100 @@ -33,6 +33,7 @@ #include <asm/kregs.h> #include <asm/vcpu.h> #include <xen/irq.h> +#include <xen/errno.h> /* * Get the machine page frame number in 16KB unit diff -r e01441c9a607 -r 50aea0ec406b xen/arch/ia64/vmx/vmx_hypercall.c --- a/xen/arch/ia64/vmx/vmx_hypercall.c Wed Aug 30 14:09:31 2006 -0500 +++ b/xen/arch/ia64/vmx/vmx_hypercall.c Wed Aug 30 22:36:18 2006 +0100 @@ -59,21 +59,23 @@ do_hvm_op(unsigned long op, XEN_GUEST_HA } else if (IS_PRIV(current->domain)) { d = find_domain_by_id(a.domid); - if (!d) + if (d == NULL) return -ESRCH; } else return -EPERM; if (op == HVMOP_set_param) { + d->arch.hvm_domain.params[a.index] = a.value; rc = 0; - d->arch.hvm_domain.params[a.index] = a.value; } - else - rc = d->arch.hvm_domain.params[a.index]; + else { + a.value = d->arch.hvm_domain.params[a.index]; + rc = copy_to_guest(arg, &a, 1) ? -EFAULT : 0; + } put_domain(d); - return rc; + break; } default: diff -r e01441c9a607 -r 50aea0ec406b xen/arch/ia64/vmx/vmx_init.c --- a/xen/arch/ia64/vmx/vmx_init.c Wed Aug 30 14:09:31 2006 -0500 +++ b/xen/arch/ia64/vmx/vmx_init.c Wed Aug 30 22:36:18 2006 +0100 @@ -206,7 +206,7 @@ vmx_create_vp(struct vcpu *v) u64 ret; vpd_t *vpd = (vpd_t *)v->arch.privregs; u64 ivt_base; - extern char vmx_ia64_ivt; + extern char vmx_ia64_ivt; /* ia64_ivt is function pointer, so need this tranlation */ ivt_base = (u64) &vmx_ia64_ivt; printk("ivt_base: 0x%lx\n", ivt_base); @@ -265,6 +265,29 @@ vmx_load_state(struct vcpu *v) * anchored in vcpu */ } +static void vmx_create_event_channels(struct vcpu *v) +{ + vcpu_iodata_t *p; + struct vcpu *o; + + if (v->vcpu_id == 0) { + /* Ugly: create event channels for every vcpu when vcpu 0 + starts, so that they're available for ioemu to bind to. */ + for_each_vcpu(v->domain, o) { + p = get_vio(v->domain, o->vcpu_id); + o->arch.arch_vmx.xen_port = p->vp_eport = + alloc_unbound_xen_event_channel(o, 0); + DPRINTK("Allocated port %d for hvm.\n", + o->arch.arch_vmx.xen_port); + } + } +} + +static void vmx_release_assist_channel(struct vcpu *v) +{ + free_xen_event_channel(v, v->arch.arch_vmx.xen_port); +} + /* * Initialize VMX envirenment for guest. Only the 1st vp/vcpu * is registered here. @@ -286,6 +309,8 @@ vmx_final_setup_guest(struct vcpu *v) #ifndef HASH_VHPT init_domain_tlb(v); #endif + vmx_create_event_channels(v); + /* v->arch.schedule_tail = arch_vmx_do_launch; */ vmx_create_vp(v); @@ -301,6 +326,15 @@ vmx_final_setup_guest(struct vcpu *v) set_bit(ARCH_VMX_INTR_ASSIST, &v->arch.arch_vmx.flags); /* Set up guest 's indicator for VTi domain*/ set_bit(ARCH_VMX_DOMAIN, &v->arch.arch_vmx.flags); +} + +void +vmx_relinquish_guest_resources(struct domain *d) +{ + struct vcpu *v; + + for_each_vcpu(d, v) + vmx_release_assist_channel(v); } void @@ -411,6 +445,9 @@ void vmx_setup_platform(struct domain *d memset(&d->shared_info->evtchn_mask[0], 0xff, sizeof(d->shared_info->evtchn_mask)); + /* initiate spinlock for pass virq */ + spin_lock_init(&d->arch.arch_vmx.virq_assist_lock); + /* Initialize the virtual interrupt lines */ vmx_virq_line_init(d); @@ -420,13 +457,5 @@ void vmx_setup_platform(struct domain *d void vmx_do_launch(struct vcpu *v) { - if (evtchn_bind_vcpu(iopacket_port(v), v->vcpu_id) < 0) { - printk("VMX domain bind port %d to vcpu %d failed!\n", - iopacket_port(v), v->vcpu_id); - domain_crash_synchronous(); - } - - clear_bit(iopacket_port(v), &v->domain->shared_info->evtchn_mask[0]); - vmx_load_all_rr(v); } diff -r e01441c9a607 -r 50aea0ec406b xen/arch/ia64/vmx/vmx_phy_mode.c --- a/xen/arch/ia64/vmx/vmx_phy_mode.c Wed Aug 30 14:09:31 2006 -0500 +++ b/xen/arch/ia64/vmx/vmx_phy_mode.c Wed Aug 30 22:36:18 2006 +0100 @@ -195,7 +195,8 @@ vmx_load_all_rr(VCPU *vcpu) (void *)vcpu->domain->shared_info, (void *)vcpu->arch.privregs, (void *)vcpu->arch.vhpt.hash, pal_vaddr ); - ia64_set_pta(vcpu->arch.arch_vmx.mpta); + ia64_set_pta(VMX(vcpu, mpta)); + ia64_set_dcr(VMX(vcpu, mdcr)); ia64_srlz_d(); ia64_set_psr(psr); diff -r e01441c9a607 -r 50aea0ec406b xen/arch/ia64/vmx/vmx_process.c --- a/xen/arch/ia64/vmx/vmx_process.c Wed Aug 30 14:09:31 2006 -0500 +++ b/xen/arch/ia64/vmx/vmx_process.c Wed Aug 30 22:36:18 2006 +0100 @@ -186,6 +186,7 @@ void leave_hypervisor_tail(struct pt_reg { struct domain *d = current->domain; struct vcpu *v = current; + int callback_irq; // FIXME: Will this work properly if doing an RFI??? if (!is_idle_domain(d) ) { // always comes from guest // struct pt_regs *user_regs = vcpu_regs(current); @@ -212,6 +213,13 @@ void leave_hypervisor_tail(struct pt_reg // VCPU(v, irr[0]) |= 1UL << 0x10; // v->arch.irq_new_pending = 1; // } + + callback_irq = d->arch.hvm_domain.params[HVM_PARAM_CALLBACK_IRQ]; + if (callback_irq != 0 && local_events_need_delivery()) { + /*inject para-device call back irq*/ + v->vcpu_info->evtchn_upcall_mask = 1; + vmx_vcpu_pend_interrupt(v, callback_irq); + } if ( v->arch.irq_new_pending ) { v->arch.irq_new_pending = 0; diff -r e01441c9a607 -r 50aea0ec406b xen/arch/ia64/vmx/vmx_support.c --- a/xen/arch/ia64/vmx/vmx_support.c Wed Aug 30 14:09:31 2006 -0500 +++ b/xen/arch/ia64/vmx/vmx_support.c Wed Aug 30 22:36:18 2006 +0100 @@ -1,4 +1,3 @@ - /* -*- Mode:C; c-basic-offset:4; tab-width:4; indent-tabs-mode:nil -*- */ /* * vmx_support.c: vmx specific support interface. @@ -22,45 +21,11 @@ #include <xen/config.h> #include <xen/sched.h> #include <xen/hypercall.h> +#include <xen/event.h> #include <public/sched.h> #include <public/hvm/ioreq.h> #include <asm/vmx.h> #include <asm/vmx_vcpu.h> - -/* - * I/O emulation should be atomic from domain point of view. However, - * when emulation code is waiting for I/O completion by blocking, - * other events like DM interrupt, VBD, etc. may come and unblock - * current exection flow. So we have to prepare for re-block if unblocked - * by non I/O completion event. After io emulation is done, re-enable - * pending indicaion if other ports are pending - */ -void vmx_wait_io(void) -{ - struct vcpu *v = current; - struct domain *d = v->domain; - int port = iopacket_port(v); - - for (;;) { - if (test_and_clear_bit(0, &v->vcpu_info->evtchn_upcall_pending) && - test_and_clear_bit(port / BITS_PER_LONG, - &v->vcpu_info->evtchn_pending_sel) && - test_and_clear_bit(port, &d->shared_info->evtchn_pending[0])) - vmx_io_assist(v); - - if (!test_bit(ARCH_VMX_IO_WAIT, &v->arch.arch_vmx.flags)) - break; - - do_sched_op_compat(SCHEDOP_block, 0); - } - - /* re-enable indication if other pending events */ - if (d->shared_info->evtchn_pending[port / BITS_PER_LONG]) - set_bit(port / BITS_PER_LONG, &v->vcpu_info->evtchn_pending_sel); - - if (v->vcpu_info->evtchn_pending_sel) - set_bit(0, &v->vcpu_info->evtchn_upcall_pending); -} /* * Only place to call vmx_io_assist is mmio/legacy_io emulation. @@ -83,17 +48,15 @@ void vmx_io_assist(struct vcpu *v) p = &vio->vp_ioreq; - if (test_bit(ARCH_VMX_IO_WAIT, &v->arch.arch_vmx.flags)) { - if (p->state != STATE_IORESP_READY) { - /* Can't block here, for the same reason as other places to - * use vmx_wait_io. Simple return is safe since vmx_wait_io will - * try to block again - */ - return; - } else - p->state = STATE_INVALID; - - clear_bit(ARCH_VMX_IO_WAIT, &v->arch.arch_vmx.flags); + if (p->state == STATE_IORESP_READY) { + p->state = STATE_INVALID; + } + else { + /* Can't block here, for the same reason as other places to + * use vmx_wait_io. Simple return is safe since vmx_wait_io will + * try to block again + */ + return; } } @@ -108,35 +71,62 @@ void vmx_io_assist(struct vcpu *v) */ void vmx_intr_assist(struct vcpu *v) { - vcpu_iodata_t *vio; - struct domain *d = v->domain; - extern void vmx_vcpu_pend_batch_interrupt(VCPU *vcpu, - unsigned long *pend_irr); - int port = iopacket_port(v); - - if (test_bit(port, &d->shared_info->evtchn_pending[0]) || - test_bit(ARCH_VMX_IO_WAIT, &v->arch.arch_vmx.flags)) - vmx_wait_io(); - - /* I/O emulation is atomic, so it's impossible to see execution flow - * out of vmx_wait_io, when guest is still waiting for response. - */ - if (test_bit(ARCH_VMX_IO_WAIT, &v->arch.arch_vmx.flags)) - panic_domain(vcpu_regs(v),"!!!Bad resume to guest before I/O emulation is done.\n"); - - /* Even without event pending, we still need to sync pending bits - * between DM and vlsapic. The reason is that interrupt delivery - * shares same event channel as I/O emulation, with corresponding - * indicator possibly cleared when vmx_wait_io(). - */ - vio = get_vio(v->domain, v->vcpu_id); - if (!vio) - panic_domain(vcpu_regs(v),"Corruption: bad shared page: %lx\n", (unsigned long)vio); - #ifdef V_IOSAPIC_READY /* Confirm virtual interrupt line signals, and set pending bits in vpd */ - if(v->vcpu_id==0) + if (spin_trylock(&v->domain->arch.arch_vmx.virq_assist_lock)) { vmx_virq_line_assist(v); + spin_unlock(&v->domain->arch.arch_vmx.virq_assist_lock); + } #endif return; } + +void vmx_send_assist_req(struct vcpu *v) +{ + ioreq_t *p; + + p = &get_vio(v->domain, v->vcpu_id)->vp_ioreq; + if (unlikely(p->state != STATE_INVALID)) { + /* This indicates a bug in the device model. Crash the + domain. */ + printk("Device model set bad IO state %d.\n", p->state); + domain_crash(v->domain); + return; + } + wmb(); + p->state = STATE_IOREQ_READY; + notify_via_xen_event_channel(v->arch.arch_vmx.xen_port); + + /* + * Waiting for MMIO completion + * like the wait_on_xen_event_channel() macro like... + * but, we can't call do_softirq() at this point.. + */ + for (;;) { + if (p->state != STATE_IOREQ_READY && + p->state != STATE_IOREQ_INPROCESS) + break; + + set_bit(_VCPUF_blocked_in_xen, ¤t->vcpu_flags); + mb(); /* set blocked status /then/ re-evaluate condition */ + if (p->state != STATE_IOREQ_READY && + p->state != STATE_IOREQ_INPROCESS) + { + clear_bit(_VCPUF_blocked_in_xen, ¤t->vcpu_flags); + break; + } + + /* I want to call __enter_scheduler() only */ + do_sched_op_compat(SCHEDOP_yield, 0); + mb(); + } + + /* the code under this line is completer phase... */ + vmx_io_assist(v); +} + +/* Wake up a vcpu whihc is waiting for interrupts to come in */ +void vmx_prod_vcpu(struct vcpu *v) +{ + vcpu_unblock(v); +} diff -r e01441c9a607 -r 50aea0ec406b xen/arch/ia64/vmx/vtlb.c --- a/xen/arch/ia64/vmx/vtlb.c Wed Aug 30 14:09:31 2006 -0500 +++ b/xen/arch/ia64/vmx/vtlb.c Wed Aug 30 22:36:18 2006 +0100 @@ -23,7 +23,7 @@ #include <linux/sched.h> #include <asm/tlb.h> -#include <asm/mm.h> +#include <xen/mm.h> #include <asm/vmx_mm_def.h> #include <asm/gcc_intrin.h> #include <linux/interrupt.h> @@ -148,13 +148,17 @@ static void vmx_vhpt_insert(thash_cb_t * rr.rrval = ia64_get_rr(ifa); head = (thash_data_t *)ia64_thash(ifa); tag = ia64_ttag(ifa); - if( INVALID_VHPT(head) ) { - len = head->len; - head->page_flags = pte; - head->len = len; - head->itir = rr.ps << 2; - head->etag = tag; - return; + cch = head; + while (cch) { + if (INVALID_VHPT(cch)) { + len = cch->len; + cch->page_flags = pte; + cch->len = len; + cch->itir = rr.ps << 2; + cch->etag = tag; + return; + } + cch = cch->next; } if(head->len>=MAX_CCN_DEPTH){ @@ -214,12 +218,22 @@ u64 guest_vhpt_lookup(u64 iha, u64 *pte) { u64 ret; thash_data_t * data; + PTA vpta; + data = vhpt_lookup(iha); if (data == NULL) { data = vtlb_lookup(current, iha, DSIDE_TLB); if (data != NULL) thash_vhpt_insert(current, data->page_flags, data->itir ,iha); } + + /* VHPT long format is not read. */ + vmx_vcpu_get_pta(current, &vpta.val); + if (vpta.vf == 1) { + *pte = 0; + return 0; + } + asm volatile ("rsm psr.ic|psr.i;;" "srlz.d;;" "ld8.s r9=[%1];;" @@ -231,11 +245,10 @@ u64 guest_vhpt_lookup(u64 iha, u64 *pte) "ssm psr.ic;;" "srlz.d;;" "ssm psr.i;;" - : "=r"(ret) : "r"(iha), "r"(pte):"memory"); + : "=r"(ret) : "r"(iha), "r"(pte):"memory"); return ret; } - /* * purge software guest tlb */ @@ -243,28 +256,29 @@ void vtlb_purge(VCPU *v, u64 va, u64 ps) void vtlb_purge(VCPU *v, u64 va, u64 ps) { thash_data_t *cur; - u64 start, end, curadr, size, psbits, tag, def_size; + u64 start, curadr, size, psbits, tag, rr_ps, num; ia64_rr vrr; thash_cb_t *hcb = &v->arch.vtlb; + vcpu_get_rr(v, va, &vrr.rrval); psbits = VMX(v, psbits[(va >> 61)]); - size = PSIZE(ps); - start = va & (-size); - end = start + size; + start = va & ~((1UL << ps) - 1); while (psbits) { curadr = start; - ps = __ffs(psbits); - psbits &= ~(1UL << ps); - def_size = PSIZE(ps); - vrr.ps = ps; - while (curadr < end) { + rr_ps = __ffs(psbits); + psbits &= ~(1UL << rr_ps); + num = 1UL << ((ps < rr_ps) ? 0 : (ps - rr_ps)); + size = PSIZE(rr_ps); + vrr.ps = rr_ps; + while (num) { cur = vsa_thash(hcb->pta, curadr, vrr.rrval, &tag); while (cur) { - if (cur->etag == tag && cur->ps == ps) + if (cur->etag == tag && cur->ps == rr_ps) cur->etag = 1UL << 63; cur = cur->next; } - curadr += def_size; + curadr += size; + num--; } } } @@ -277,14 +291,14 @@ static void vhpt_purge(VCPU *v, u64 va, { //thash_cb_t *hcb = &v->arch.vhpt; thash_data_t *cur; - u64 start, end, size, tag; + u64 start, size, tag, num; ia64_rr rr; - size = PSIZE(ps); - start = va & (-size); - end = start + size; - rr.rrval = ia64_get_rr(va); - size = PSIZE(rr.ps); - while(start < end){ + + start = va & ~((1UL << ps) - 1); + rr.rrval = ia64_get_rr(va); + size = PSIZE(rr.ps); + num = 1UL << ((ps < rr.ps) ? 0 : (ps - rr.ps)); + while (num) { cur = (thash_data_t *)ia64_thash(start); tag = ia64_ttag(start); while (cur) { @@ -293,6 +307,7 @@ static void vhpt_purge(VCPU *v, u64 va, cur = cur->next; } start += size; + num--; } machine_tlb_purge(va, ps); } @@ -347,24 +362,20 @@ void vtlb_insert(VCPU *v, u64 pte, u64 i u64 tag, len; thash_cb_t *hcb = &v->arch.vtlb; vcpu_get_rr(v, va, &vrr.rrval); -#ifdef VTLB_DEBUG - if (vrr.ps != itir_ps(itir)) { -// machine_tlb_insert(hcb->vcpu, entry); - panic_domain(NULL, "not preferred ps with va: 0x%lx vrr.ps=%d ps=%ld\n", - va, vrr.ps, itir_ps(itir)); - return; - } -#endif vrr.ps = itir_ps(itir); VMX(v, psbits[va >> 61]) |= (1UL << vrr.ps); hash_table = vsa_thash(hcb->pta, va, vrr.rrval, &tag); - if( INVALID_TLB(hash_table) ) { - len = hash_table->len; - hash_table->page_flags = pte; - hash_table->len = len; - hash_table->itir=itir; - hash_table->etag=tag; - return; + cch = hash_table; + while (cch) { + if (INVALID_TLB(cch)) { + len = cch->len; + cch->page_flags = pte; + cch->len = len; + cch->itir=itir; + cch->etag=tag; + return; + } + cch = cch->next; } if (hash_table->len>=MAX_CCN_DEPTH){ thash_recycle_cch(hcb, hash_table); @@ -458,10 +469,6 @@ void thash_purge_and_insert(VCPU *v, u64 ps = itir_ps(itir); vcpu_get_rr(current, ifa, &vrr.rrval); mrr.rrval = ia64_get_rr(ifa); -// if (vrr.ps != itir_ps(itir)) { -// printf("not preferred ps with va: 0x%lx vrr.ps=%d ps=%ld\n", -// ifa, vrr.ps, itir_ps(itir)); -// } if(VMX_DOMAIN(v)){ /* Ensure WB attribute if pte is related to a normal mem page, * which is required by vga acceleration since qemu maps shared diff -r e01441c9a607 -r 50aea0ec406b xen/arch/ia64/xen/acpi.c --- a/xen/arch/ia64/xen/acpi.c Wed Aug 30 14:09:31 2006 -0500 +++ b/xen/arch/ia64/xen/acpi.c Wed Aug 30 22:36:18 2006 +0100 @@ -51,6 +51,9 @@ #include <asm/numa.h> #include <asm/sal.h> #include <asm/hw_irq.h> +#ifdef XEN +#include <xen/errno.h> +#endif #define BAD_MADT_ENTRY(entry, end) ( \ (!entry) || (unsigned long)entry + sizeof(*entry) > end || \ diff -r e01441c9a607 -r 50aea0ec406b xen/arch/ia64/xen/dom0_ops.c --- a/xen/arch/ia64/xen/dom0_ops.c Wed Aug 30 14:09:31 2006 -0500 +++ b/xen/arch/ia64/xen/dom0_ops.c Wed Aug 30 22:36:18 2006 +0100 @@ -21,6 +21,7 @@ #include <asm/vmx.h> #include <asm/dom_fw.h> #include <xen/iocap.h> +#include <xen/errno.h> void build_physmap_table(struct domain *d); @@ -39,8 +40,8 @@ long arch_do_domctl(xen_domctl_t *op, XE { unsigned long i; struct domain *d = find_domain_by_id(op->domain); - unsigned long start_page = op->u.getmemlist.max_pfns >> 32; - unsigned long nr_pages = op->u.getmemlist.max_pfns & 0xffffffff; + unsigned long start_page = op->u.getmemlist.start_pfn; + unsigned long nr_pages = op->u.getmemlist.max_pfns; unsigned long mfn; if ( d == NULL ) { diff -r e01441c9a607 -r 50aea0ec406b xen/arch/ia64/xen/dom_fw.c --- a/xen/arch/ia64/xen/dom_fw.c Wed Aug 30 14:09:31 2006 -0500 +++ b/xen/arch/ia64/xen/dom_fw.c Wed Aug 30 22:36:18 2006 +0100 @@ -21,28 +21,23 @@ #include <asm/fpswa.h> #include <xen/version.h> #include <xen/acpi.h> +#include <xen/errno.h> #include <asm/dom_fw.h> #include <asm/bundle.h> -static void dom_fw_init (struct domain *d, struct ia64_boot_param *bp, char *fw_mem, int fw_mem_size, unsigned long maxmem); - -extern struct domain *dom0; +#define ONE_MB (1UL << 20) extern unsigned long running_on_sim; -/* Note: two domains cannot be created simulteanously! */ -static unsigned long dom_fw_base_mpa = -1; -static unsigned long imva_fw_base = -1; - #define FW_VENDOR "X\0e\0n\0/\0i\0a\0\066\0\064\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" -#define MAKE_MD(typ, attr, start, end, abs) \ +#define MAKE_MD(typ, attr, start, end) \ do { \ - md = efi_memmap + i++; \ + md = tables->efi_memmap + i++; \ md->type = typ; \ md->pad = 0; \ - md->phys_addr = abs ? start : start_mpaddr + start; \ + md->phys_addr = start; \ md->virt_addr = 0; \ md->num_pages = (end - start) >> EFI_PAGE_SHIFT; \ md->attribute = attr; \ @@ -51,44 +46,31 @@ static unsigned long imva_fw_base = -1; #define EFI_HYPERCALL_PATCH(tgt, call) \ do { \ dom_efi_hypercall_patch(d, FW_HYPERCALL_##call##_PADDR, \ - FW_HYPERCALL_##call); \ - tgt = dom_pa((unsigned long) pfn); \ - *pfn++ = FW_HYPERCALL_##call##_PADDR + start_mpaddr; \ - *pfn++ = 0; \ + FW_HYPERCALL_##call, hypercalls_imva); \ + /* Descriptor address. */ \ + tables->efi_runtime.tgt = \ + FW_FIELD_MPA(func_ptrs) + 8 * pfn; \ + /* Descriptor. */ \ + tables->func_ptrs[pfn++] = FW_HYPERCALL_##call##_PADDR; \ + tables->func_ptrs[pfn++] = 0; \ } while (0) - -// return domain (meta)physical address for a given imva -// this function is a call-back from dom_fw_init -static unsigned long -dom_pa(unsigned long imva) -{ - if (dom_fw_base_mpa == -1 || imva_fw_base == -1) { - printf("dom_pa: uninitialized! (spinning...)\n"); - while(1); - } - if (imva - imva_fw_base > PAGE_SIZE) { - printf("dom_pa: bad offset! imva=0x%lx, imva_fw_base=0x%lx (spinning...)\n", - imva, imva_fw_base); - while(1); - } - return dom_fw_base_mpa + (imva - imva_fw_base); -} // allocate a page for fw // build_physmap_table() which is called by new_thread() // does for domU. -#define ASSIGN_NEW_DOMAIN_PAGE_IF_DOM0(d, mpaddr) \ - do { \ - if ((d) == dom0) { \ - assign_new_domain0_page((d), (mpaddr)); \ - } \ - } while (0) +static inline void +assign_new_domain_page_if_dom0(struct domain *d, unsigned long mpaddr) +{ + if (d == dom0) + assign_new_domain0_page(d, mpaddr); +} /************************************************************************** Hypercall bundle creation **************************************************************************/ -static void build_hypercall_bundle(UINT64 *imva, UINT64 brkimm, UINT64 hypnum, UINT64 ret) +static void +build_hypercall_bundle(u64 *imva, u64 brkimm, u64 hypnum, u64 ret) { INST64_A5 slot0; INST64_I19 slot1; @@ -104,8 +86,8 @@ static void build_hypercall_bundle(UINT6 slot1.inst = 0; slot1.qp = 0; slot1.x6 = 0; slot1.x3 = 0; slot1.major = 0x0; slot1.imm20 = brkimm; slot1.i = brkimm >> 20; - // if ret slot2: br.ret.sptk.many rp - // else slot2: br.cond.sptk.many rp + // if ret slot2: br.ret.sptk.many rp + // else slot2: br.cond.sptk.many rp slot2.inst = 0; slot2.qp = 0; slot2.p = 1; slot2.b2 = 0; slot2.wh = 0; slot2.d = 0; slot2.major = 0x0; if (ret) { @@ -125,7 +107,8 @@ static void build_hypercall_bundle(UINT6 ia64_fc(imva + 1); } -static void build_pal_hypercall_bundles(UINT64 *imva, UINT64 brkimm, UINT64 hypnum) +static void +build_pal_hypercall_bundles(u64 *imva, u64 brkimm, u64 hypnum) { extern unsigned long pal_call_stub[]; IA64_BUNDLE bundle; @@ -162,76 +145,68 @@ static void build_pal_hypercall_bundles( } // builds a hypercall bundle at domain physical address -static void dom_fpswa_hypercall_patch(struct domain *d) +static void +dom_fpswa_hypercall_patch(struct domain *d, unsigned long imva) { unsigned long *entry_imva, *patch_imva; - unsigned long entry_paddr = FW_HYPERCALL_FPSWA_ENTRY_PADDR; - unsigned long patch_paddr = FW_HYPERCALL_FPSWA_PATCH_PADDR; - - ASSIGN_NEW_DOMAIN_PAGE_IF_DOM0(d, entry_paddr); - ASSIGN_NEW_DOMAIN_PAGE_IF_DOM0(d, patch_paddr); - entry_imva = domain_mpa_to_imva(d, entry_paddr); - patch_imva = domain_mpa_to_imva(d, patch_paddr); - + const unsigned long entry_paddr = FW_HYPERCALL_FPSWA_ENTRY_PADDR; + const unsigned long patch_paddr = FW_HYPERCALL_FPSWA_PATCH_PADDR; + + entry_imva = (unsigned long *)(imva + entry_paddr - + FW_HYPERCALL_BASE_PADDR); + patch_imva = (unsigned long *)(imva + patch_paddr - + FW_HYPERCALL_BASE_PADDR); + + /* Descriptor. */ *entry_imva++ = patch_paddr; *entry_imva = 0; - build_hypercall_bundle(patch_imva, d->arch.breakimm, FW_HYPERCALL_FPSWA, 1); + + build_hypercall_bundle(patch_imva, d->arch.breakimm, + FW_HYPERCALL_FPSWA, 1); } // builds a hypercall bundle at domain physical address -static void dom_efi_hypercall_patch(struct domain *d, unsigned long paddr, unsigned long hypercall) -{ - unsigned long *imva; - - ASSIGN_NEW_DOMAIN_PAGE_IF_DOM0(d, paddr); - imva = domain_mpa_to_imva(d, paddr); - build_hypercall_bundle(imva, d->arch.breakimm, hypercall, 1); +static void +dom_efi_hypercall_patch(struct domain *d, unsigned long paddr, + unsigned long hypercall, unsigned long imva) +{ + build_hypercall_bundle((u64 *)(imva + paddr - FW_HYPERCALL_BASE_PADDR), + d->arch.breakimm, hypercall, 1); } // builds a hypercall bundle at domain physical address -static void dom_fw_hypercall_patch(struct domain *d, unsigned long paddr, unsigned long hypercall,unsigned long ret) -{ - unsigned long *imva; - - ASSIGN_NEW_DOMAIN_PAGE_IF_DOM0(d, paddr); - imva = domain_mpa_to_imva(d, paddr); - build_hypercall_bundle(imva, d->arch.breakimm, hypercall, ret); -} - -static void dom_fw_pal_hypercall_patch(struct domain *d, unsigned long paddr) -{ - unsigned long *imva; - - ASSIGN_NEW_DOMAIN_PAGE_IF_DOM0(d, paddr); - imva = domain_mpa_to_imva(d, paddr); - build_pal_hypercall_bundles(imva, d->arch.breakimm, FW_HYPERCALL_PAL_CALL); -} - - -void dom_fw_setup(struct domain *d, unsigned long bp_mpa, unsigned long maxmem) -{ - struct ia64_boot_param *bp; - - dom_fw_base_mpa = 0; - ASSIGN_NEW_DOMAIN_PAGE_IF_DOM0(d, dom_fw_base_mpa); - imva_fw_base = (unsigned long) domain_mpa_to_imva(d, dom_fw_base_mpa); - ASSIGN_NEW_DOMAIN_PAGE_IF_DOM0(d, bp_mpa); - bp = domain_mpa_to_imva(d, bp_mpa); - dom_fw_init(d, bp, (char *) imva_fw_base, PAGE_SIZE, maxmem); -} - - -/* the following heavily leveraged from linux/arch/ia64/hp/sim/fw-emu.c */ - -#define NFUNCPTRS 20 +static void +dom_fw_hypercall_patch(struct domain *d, unsigned long paddr, + unsigned long hypercall,unsigned long ret, + unsigned long imva) +{ + build_hypercall_bundle((u64 *)(imva + paddr - FW_HYPERCALL_BASE_PADDR), + d->arch.breakimm, hypercall, ret); +} + +static void +dom_fw_pal_hypercall_patch(struct domain *d, unsigned long paddr, + unsigned long imva) +{ + build_pal_hypercall_bundles((u64*)(imva + paddr - + FW_HYPERCALL_BASE_PADDR), + d->arch.breakimm, FW_HYPERCALL_PAL_CALL); +} static inline void print_md(efi_memory_desc_t *md) { - printk("domain mem: type=%2u, attr=0x%016lx, range=[0x%016lx-0x%016lx) (%luMB)\n", - md->type, md->attribute, md->phys_addr, - md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT), - md->num_pages >> (20 - EFI_PAGE_SHIFT)); + u64 size; + + printk("dom mem: type=%2u, attr=0x%016lx, range=[0x%016lx-0x%016lx) ", + md->type, md->attribute, md->phys_addr, + md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT)); + + size = md->num_pages << EFI_PAGE_SHIFT; + if (size > ONE_MB) + printf ("(%luMB)\n", size >> 20); + else + printf ("(%luKB)\n", size >> 10); } static u32 lsapic_nbr; @@ -316,6 +291,8 @@ struct fake_acpi_tables { u8 pm1a_cnt_blk[1]; u8 pm_tmr_blk[4]; }; +#define ACPI_TABLE_MPA(field) \ + FW_ACPI_BASE_PADDR + offsetof(struct fake_acpi_tables, field); /* Create enough of an ACPI structure to make the guest OS ACPI happy. */ static void @@ -345,8 +322,8 @@ dom_fw_fake_acpi(struct domain *d, struc xsdt->asl_compiler_revision = (xen_major_version() << 16) | xen_minor_version(); - xsdt->table_offset_entry[0] = dom_pa((unsigned long) fadt); - tables->madt_ptr = dom_pa((unsigned long) madt); + xsdt->table_offset_entry[0] = ACPI_TABLE_MPA(fadt); + tables->madt_ptr = ACPI_TABLE_MPA(madt); xsdt->checksum = generate_acpi_checksum(xsdt, xsdt->length); @@ -364,8 +341,8 @@ dom_fw_fake_acpi(struct domain *d, struc facs->version = 1; facs->length = sizeof(struct facs_descriptor_rev2); - fadt->xfirmware_ctrl = dom_pa((unsigned long) facs); - fadt->Xdsdt = dom_pa((unsigned long) dsdt); + fadt->xfirmware_ctrl = ACPI_TABLE_MPA(facs); + fadt->Xdsdt = ACPI_TABLE_MPA(dsdt); /* * All of the below FADT entries are filled it to prevent warnings @@ -375,15 +352,15 @@ dom_fw_fake_acpi(struct domain *d, struc fadt->pm1_evt_len = 4; fadt->xpm1a_evt_blk.address_space_id = ACPI_ADR_SPACE_SYSTEM_MEMORY; fadt->xpm1a_evt_blk.register_bit_width = 8; - fadt->xpm1a_evt_blk.address = dom_pa((unsigned long) &tables->pm1a_evt_blk); + fadt->xpm1a_evt_blk.address = ACPI_TABLE_MPA(pm1a_evt_blk); fadt->pm1_cnt_len = 1; fadt->xpm1a_cnt_blk.address_space_id = ACPI_ADR_SPACE_SYSTEM_MEMORY; fadt->xpm1a_cnt_blk.register_bit_width = 8; - fadt->xpm1a_cnt_blk.address = dom_pa((unsigned long) &tables->pm1a_cnt_blk); + fadt->xpm1a_cnt_blk.address = ACPI_TABLE_MPA(pm1a_cnt_blk); fadt->pm_tm_len = 4; fadt->xpm_tmr_blk.address_space_id = ACPI_ADR_SPACE_SYSTEM_MEMORY; fadt->xpm_tmr_blk.register_bit_width = 8; - fadt->xpm_tmr_blk.address = dom_pa((unsigned long) &tables->pm_tmr_blk); + fadt->xpm_tmr_blk.address = ACPI_TABLE_MPA(pm_tmr_blk); fadt->checksum = generate_acpi_checksum(fadt, fadt->length); @@ -392,7 +369,7 @@ dom_fw_fake_acpi(struct domain *d, struc strcpy(rsdp->oem_id, "XEN"); rsdp->revision = 2; /* ACPI 2.0 includes XSDT */ rsdp->length = sizeof(struct acpi20_table_rsdp); - rsdp->xsdt_address = dom_pa((unsigned long) xsdt); + rsdp->xsdt_address = ACPI_TABLE_MPA(xsdt); rsdp->checksum = generate_acpi_checksum(rsdp, ACPI_RSDP_CHECKSUM_LENGTH); @@ -467,115 +444,6 @@ dom_fw_fake_acpi(struct domain *d, struc return; } -#define NUM_EFI_SYS_TABLES 6 -#define NUM_MEM_DESCS 64 //large enough - -struct dom0_passthrough_arg { - struct domain* d; - int flags; - efi_memory_desc_t *md; - int* i; -}; - -static int -dom_fw_dom0_passthrough(efi_memory_desc_t *md, void *arg__) -{ - struct dom0_passthrough_arg* arg = (struct dom0_passthrough_arg*)arg__; - unsigned long paddr; - struct domain* d = arg->d; - u64 start = md->phys_addr; - u64 size = md->num_pages << EFI_PAGE_SHIFT; - - if (md->type == EFI_MEMORY_MAPPED_IO || - md->type == EFI_MEMORY_MAPPED_IO_PORT_SPACE) { - - //XXX some machine has large mmio area whose size is about several TB. - // It requires impractical memory to map such a huge region - // to a domain. - // For now we don't map it, but later we must fix this. - if (md->type == EFI_MEMORY_MAPPED_IO && (size > 0x100000000UL)) - return 0; - - paddr = assign_domain_mmio_page(d, start, size); - } else - paddr = assign_domain_mach_page(d, start, size, arg->flags); - - BUG_ON(md->type != EFI_RUNTIME_SERVICES_CODE && - md->type != EFI_RUNTIME_SERVICES_DATA && - md->type != EFI_ACPI_RECLAIM_MEMORY && - md->type != EFI_ACPI_MEMORY_NVS && - md->type != EFI_RESERVED_TYPE && - md->type != EFI_MEMORY_MAPPED_IO && - md->type != EFI_MEMORY_MAPPED_IO_PORT_SPACE); - - arg->md->type = md->type; - arg->md->pad = 0; - arg->md->phys_addr = paddr; - arg->md->virt_addr = 0; - arg->md->num_pages = md->num_pages; - arg->md->attribute = md->attribute; - - (*arg->i)++; - arg->md++; - return 0; -} - -/* - * Create dom0 MDT entries for conventional memory below 1MB. Without - * this Linux will assume VGA is present because 0xA0000 will always - * be either a hole in the MDT or an I/O region via the passthrough. - */ -static int -dom_fw_dom0_lowmem(efi_memory_desc_t *md, void *arg__) -{ - struct dom0_passthrough_arg* arg = (struct dom0_passthrough_arg*)arg__; - u64 end = min(HYPERCALL_START, - md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT)); - - BUG_ON(md->type != EFI_CONVENTIONAL_MEMORY); - - /* avoid hypercall area */ - if (md->phys_addr >= HYPERCALL_START) - return 0; - - /* avoid firmware base area */ - if (md->phys_addr < dom_pa(imva_fw_base)) - end = min(end, dom_pa(imva_fw_base)); - else if (md->phys_addr < dom_pa(imva_fw_base + PAGE_SIZE)) { - if (end < dom_pa(imva_fw_base + PAGE_SIZE)) - return 0; - md->phys_addr = dom_pa(imva_fw_base + PAGE_SIZE); - } - - arg->md->type = md->type; - arg->md->pad = 0; - arg->md->phys_addr = md->phys_addr; - arg->md->virt_addr = 0; - arg->md->num_pages = (end - md->phys_addr) >> EFI_PAGE_SHIFT; - arg->md->attribute = md->attribute; - - (*arg->i)++; - arg->md++; - - /* if firmware area spliced the md, add the upper part here */ - if (end == dom_pa(imva_fw_base)) { - end = min(HYPERCALL_START, - md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT)); - if (end > dom_pa(imva_fw_base + PAGE_SIZE)) { - arg->md->type = md->type; - arg->md->pad = 0; - arg->md->phys_addr = dom_pa(imva_fw_base + PAGE_SIZE); - arg->md->virt_addr = 0; - arg->md->num_pages = (end - arg->md->phys_addr) >> EFI_PAGE_SHIFT; - arg->md->attribute = md->attribute; - - (*arg->i)++; - arg->md++; - } - } - return 0; -} - static int efi_mdt_cmp(const void *a, const void *b) { @@ -595,279 +463,403 @@ efi_mdt_cmp(const void *a, const void *b return 0; } +#define NFUNCPTRS 16 +#define NUM_EFI_SYS_TABLES 6 +#define NUM_MEM_DESCS 64 //large enough + +struct fw_tables { + efi_system_table_t efi_systab; + efi_runtime_services_t efi_runtime; + efi_config_table_t efi_tables[NUM_EFI_SYS_TABLES]; + + struct ia64_sal_systab sal_systab; + struct ia64_sal_desc_entry_point sal_ed; + struct ia64_sal_desc_ap_wakeup sal_wakeup; + /* End of SAL descriptors. Do not forget to update checkum bound. */ + + fpswa_interface_t fpswa_inf; + efi_memory_desc_t efi_memmap[NUM_MEM_DESCS]; + unsigned long func_ptrs[2*NFUNCPTRS]; + struct xen_sal_data sal_data; + unsigned char fw_vendor[sizeof(FW_VENDOR)]; +}; +#define FW_FIELD_MPA(field) \ + FW_TABLES_BASE_PADDR + offsetof(struct fw_tables, field) + +/* Complete the dom0 memmap. */ +static int +complete_dom0_memmap(struct domain *d, + struct fw_tables *tables, + unsigned long maxmem, + int num_mds) +{ + efi_memory_desc_t *md; + u64 addr; + int j; + void *efi_map_start, *efi_map_end, *p; + u64 efi_desc_size; + int i; + + /* Walk through all MDT entries. + Copy all interesting entries. */ + efi_map_start = __va(ia64_boot_param->efi_memmap); + efi_map_end = efi_map_start + ia64_boot_param->efi_memmap_size; + efi_desc_size = ia64_boot_param->efi_memdesc_size; + + for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) { + const efi_memory_desc_t *md = p; + efi_memory_desc_t *dom_md = &tables->efi_memmap[num_mds]; + u64 start = md->phys_addr; + u64 size = md->num_pages << EFI_PAGE_SHIFT; + u64 end = start + size; + + switch (md->type) { + case EFI_RUNTIME_SERVICES_CODE: + case EFI_RUNTIME_SERVICES_DATA: + case EFI_ACPI_RECLAIM_MEMORY: + case EFI_ACPI_MEMORY_NVS: + case EFI_RESERVED_TYPE: + /* Map into dom0 - All these are writable. */ + assign_domain_mach_page(d, start, size, + ASSIGN_writable); + /* Fall-through. */ + case EFI_MEMORY_MAPPED_IO: + /* Will be mapped with ioremap. */ + /* Copy descriptor. */ + *dom_md = *md; + dom_md->virt_addr = 0; + num_mds++; + break; + + case EFI_MEMORY_MAPPED_IO_PORT_SPACE: + /* Map into dom0. */ + assign_domain_mmio_page(d, start, size); + /* Copy descriptor. */ + *dom_md = *md; + dom_md->virt_addr = 0; + num_mds++; + break; + + case EFI_CONVENTIONAL_MEMORY: + case EFI_LOADER_CODE: + case EFI_LOADER_DATA: + case EFI_BOOT_SERVICES_CODE: + case EFI_BOOT_SERVICES_DATA: + /* Create dom0 MDT entries for conventional memory + below 1MB. Without this Linux will assume VGA is + present because 0xA0000 will always be either a hole + in the MDT or an I/O region via the passthrough. */ + + end = min(ONE_MB, end); + + /* Avoid firmware and hypercall area. + We know they are 0-based. */ + if (end < FW_END_PADDR || start >= ONE_MB) + break; + if (start < FW_END_PADDR) + start = FW_END_PADDR; + + dom_md->type = EFI_CONVENTIONAL_MEMORY; + dom_md->phys_addr = start; + dom_md->virt_addr = 0; + dom_md->num_pages = (end - start) >> EFI_PAGE_SHIFT; + dom_md->attribute = md->attribute; + num_mds++; + break; + + case EFI_UNUSABLE_MEMORY: + case EFI_PAL_CODE: + /* Discard. */ + break; + + default: + /* Print a warning but continue. */ + printf("complete_dom0_memmap: warning: " + "unhandled MDT entry type %u\n", md->type); + } + } + BUG_ON(num_mds > NUM_MEM_DESCS); + + sort(tables->efi_memmap, num_mds, sizeof(efi_memory_desc_t), + efi_mdt_cmp, NULL); + + /* find gaps and fill them with conventional memory */ + i = num_mds; + for (j = 0; j < num_mds; j++) { + unsigned long end; + unsigned long next_start; + + md = &tables->efi_memmap[j]; + end = md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT); + + if (j + 1 < num_mds) { + efi_memory_desc_t* next_md; + next_md = &tables->efi_memmap[j + 1]; + next_start = next_md->phys_addr; + + /* Have just been sorted. */ + BUG_ON(end > next_start); + + /* No room for memory! */ + if (end == next_start) + continue; + + if (next_start > maxmem) + next_start = maxmem; + } + else + next_start = maxmem; + + /* Avoid "legacy" low memory addresses + and the HYPERCALL area. */ + if (end < ONE_MB) + end = ONE_MB; + + // clip the range and align to PAGE_SIZE + next_start = next_start & PAGE_MASK; + end = PAGE_ALIGN(end); + + /* No room for memory. */ + if (end >= next_start) + continue; + + MAKE_MD(EFI_CONVENTIONAL_MEMORY, EFI_MEMORY_WB, + end, next_start); + + if (next_start >= maxmem) + break; + } + num_mds = i; + BUG_ON(num_mds > NUM_MEM_DESCS); + sort(tables->efi_memmap, num_mds, sizeof(efi_memory_desc_t), + efi_mdt_cmp, NULL); + + // dom0 doesn't need build_physmap_table() + // see arch_set_info_guest() + // instead we allocate pages manually. + for (i = 0; i < num_mds; i++) { + md = &tables->efi_memmap[i]; + if (md->phys_addr > maxmem) + break; + + if (md->type == EFI_LOADER_DATA || + md->type == EFI_PAL_CODE || + md->type == EFI_CONVENTIONAL_MEMORY) { + unsigned long start = md->phys_addr & PAGE_MASK; + unsigned long end = md->phys_addr + + (md->num_pages << EFI_PAGE_SHIFT); + + if (end == start) { + /* md->num_pages = 0 is allowed. */ + continue; + } + if (end > (max_page << PAGE_SHIFT)) + end = (max_page << PAGE_SHIFT); + + for (addr = start; addr < end; addr += PAGE_SIZE) + assign_new_domain0_page(d, addr); + } + } + // Map low-memory holes & unmapped MMIO for legacy drivers + for (addr = 0; addr < ONE_MB; addr += PAGE_SIZE) { + if (domain_page_mapped(d, addr)) + continue; + + if (efi_mmio(addr, PAGE_SIZE)) + assign_domain_mmio_page(d, addr, PAGE_SIZE); + } + return num_mds; +} + static void -dom_fw_init (struct domain *d, struct ia64_boot_param *bp, char *fw_mem, int fw_mem_size, unsigned long maxmem) -{ - efi_system_table_t *efi_systab; - efi_runtime_services_t *efi_runtime; - efi_config_table_t *efi_tables; - struct ia64_sal_systab *sal_systab; - struct ia64_sal_desc_entry_point *sal_ed; - struct ia64_sal_desc_ap_wakeup *sal_wakeup; - fpswa_interface_t *fpswa_inf; - efi_memory_desc_t *efi_memmap, *md; - struct xen_sal_data *sal_data; - unsigned long *pfn; - unsigned char checksum = 0; - char *cp, *fw_vendor; - int num_mds, j, i = 0; - const unsigned long start_mpaddr = 0; - -/* FIXME: should check size but for now we have a whole MB to play with. - And if stealing code from fw-emu.c, watch out for new fw_vendor on the end! - if (fw_mem_size < sizeof(fw_mem_proto)) { - printf("sys_fw_init: insufficient space for fw_mem\n"); - return 0; - } -*/ - memset(fw_mem, 0, fw_mem_size); - - cp = fw_mem; - efi_systab = (void *) cp; cp += sizeof(*efi_systab); - efi_runtime = (void *) cp; cp += sizeof(*efi_runtime); - efi_tables = (void *) cp; cp += NUM_EFI_SYS_TABLES * sizeof(*efi_tables); - sal_systab = (void *) cp; cp += sizeof(*sal_systab); - sal_ed = (void *) cp; cp += sizeof(*sal_ed); - sal_wakeup = (void *) cp; cp += sizeof(*sal_wakeup); - fpswa_inf = (void *) cp; cp += sizeof(*fpswa_inf); - efi_memmap = (void *) cp; cp += NUM_MEM_DESCS*sizeof(*efi_memmap); - pfn = (void *) cp; cp += NFUNCPTRS * 2 * sizeof(pfn); - sal_data = (void *) cp; cp += sizeof(*sal_data); +dom_fw_init(struct domain *d, + struct ia64_boot_param *bp, + struct fw_tables *tables, + unsigned long hypercalls_imva, + unsigned long maxmem) +{ + efi_memory_desc_t *md; + unsigned long pfn; + unsigned char checksum; + char *cp; + int num_mds, i; + + memset(tables, 0, sizeof(struct fw_tables)); /* Initialise for EFI_SET_VIRTUAL_ADDRESS_MAP emulation */ - d->arch.efi_runtime = efi_runtime; - d->arch.fpswa_inf = fpswa_inf; - d->arch.sal_data = sal_data; - - memset(efi_systab, 0, sizeof(efi_systab)); - efi_systab->hdr.signature = EFI_SYSTEM_TABLE_SIGNATURE; - efi_systab->hdr.revision = EFI_SYSTEM_TABLE_REVISION; - efi_systab->hdr.headersize = sizeof(efi_systab->hdr); - fw_vendor = cp; - cp += sizeof(FW_VENDOR) + (8-((unsigned long)cp & 7)); // round to 64-bit boundary - - memcpy(fw_vendor,FW_VENDOR,sizeof(FW_VENDOR)); - efi_systab->fw_vendor = dom_pa((unsigned long) fw_vendor); - efi_systab->fw_revision = 1; - efi_systab->runtime = (void *) dom_pa((unsigned long) efi_runtime); - efi_systab->nr_tables = NUM_EFI_SYS_TABLES; - efi_systab->tables = dom_pa((unsigned long) efi_tables); - - efi_runtime->hdr.signature = EFI_RUNTIME_SERVICES_SIGNATURE; - efi_runtime->hdr.revision = EFI_RUNTIME_SERVICES_REVISION; - efi_runtime->hdr.headersize = sizeof(efi_runtime->hdr); - - EFI_HYPERCALL_PATCH(efi_runtime->get_time,EFI_GET_TIME); - EFI_HYPERCALL_PATCH(efi_runtime->set_time,EFI_SET_TIME); - EFI_HYPERCALL_PATCH(efi_runtime->get_wakeup_time,EFI_GET_WAKEUP_TIME); - EFI_HYPERCALL_PATCH(efi_runtime->set_wakeup_time,EFI_SET_WAKEUP_TIME); - EFI_HYPERCALL_PATCH(efi_runtime->set_virtual_address_map,EFI_SET_VIRTUAL_ADDRESS_MAP); - EFI_HYPERCALL_PATCH(efi_runtime->get_variable,EFI_GET_VARIABLE); - EFI_HYPERCALL_PATCH(efi_runtime->get_next_variable,EFI_GET_NEXT_VARIABLE); - EFI_HYPERCALL_PATCH(efi_runtime->set_variable,EFI_SET_VARIABLE); - EFI_HYPERCALL_PATCH(efi_runtime->get_next_high_mono_count,EFI_GET_NEXT_HIGH_MONO_COUNT); - EFI_HYPERCALL_PATCH(efi_runtime->reset_system,EFI_RESET_SYSTEM); - - efi_tables[0].guid = SAL_SYSTEM_TABLE_GUID; - efi_tables[0].table = dom_pa((unsigned long) sal_systab); + d->arch.efi_runtime = &tables->efi_runtime; + d->arch.fpswa_inf = &tables->fpswa_inf; + d->arch.sal_data = &tables->sal_data; + + /* EFI systab. */ + tables->efi_systab.hdr.signature = EFI_SYSTEM_TABLE_SIGNATURE; + tables->efi_systab.hdr.revision = EFI_SYSTEM_TABLE_REVISION; + tables->efi_systab.hdr.headersize = sizeof(tables->efi_systab.hdr); + + memcpy(tables->fw_vendor,FW_VENDOR,sizeof(FW_VENDOR)); + tables->efi_systab.fw_vendor = FW_FIELD_MPA(fw_vendor); + tables->efi_systab.fw_revision = 1; + tables->efi_systab.runtime = (void *)FW_FIELD_MPA(efi_runtime); + tables->efi_systab.nr_tables = NUM_EFI_SYS_TABLES; + tables->efi_systab.tables = FW_FIELD_MPA(efi_tables); + + /* EFI runtime. */ + tables->efi_runtime.hdr.signature = EFI_RUNTIME_SERVICES_SIGNATURE; + tables->efi_runtime.hdr.revision = EFI_RUNTIME_SERVICES_REVISION; + tables->efi_runtime.hdr.headersize = sizeof(tables->efi_runtime.hdr); + + pfn = 0; + EFI_HYPERCALL_PATCH(get_time,EFI_GET_TIME); + EFI_HYPERCALL_PATCH(set_time,EFI_SET_TIME); + EFI_HYPERCALL_PATCH(get_wakeup_time,EFI_GET_WAKEUP_TIME); + EFI_HYPERCALL_PATCH(set_wakeup_time,EFI_SET_WAKEUP_TIME); + EFI_HYPERCALL_PATCH(set_virtual_address_map, + EFI_SET_VIRTUAL_ADDRESS_MAP); + EFI_HYPERCALL_PATCH(get_variable,EFI_GET_VARIABLE); + EFI_HYPERCALL_PATCH(get_next_variable,EFI_GET_NEXT_VARIABLE); + EFI_HYPERCALL_PATCH(set_variable,EFI_SET_VARIABLE); + EFI_HYPERCALL_PATCH(get_next_high_mono_count, + EFI_GET_NEXT_HIGH_MONO_COUNT); + EFI_HYPERCALL_PATCH(reset_system,EFI_RESET_SYSTEM); + + /* System tables. */ + tables->efi_tables[0].guid = SAL_SYSTEM_TABLE_GUID; + tables->efi_tables[0].table = FW_FIELD_MPA(sal_systab); for (i = 1; i < NUM_EFI_SYS_TABLES; i++) { - efi_tables[i].guid = NULL_GUID; - efi_tables[i].table = 0; - } + tables->efi_tables[i].guid = NULL_GUID; + tables->efi_tables[i].table = 0; + } + i = 1; if (d == dom0) { + /* Write messages to the console. */ + touch_acpi_table(); + printf("Domain0 EFI passthrough:"); - i = 1; if (efi.mps) { - efi_tables[i].guid = MPS_TABLE_GUID; - efi_tables[i].table = __pa(efi.mps); - printf(" MPS=0x%lx",efi_tables[i].table); + tables->efi_tables[i].guid = MPS_TABLE_GUID; + tables->efi_tables[i].table = __pa(efi.mps); + printf(" MPS=0x%lx",tables->efi_tables[i].table); i++; } - touch_acpi_table(); - if (efi.acpi20) { - efi_tables[i].guid = ACPI_20_TABLE_GUID; - efi_tables[i].table = __pa(efi.acpi20); - printf(" ACPI 2.0=0x%lx",efi_tables[i].table); + tables->efi_tables[i].guid = ACPI_20_TABLE_GUID; + tables->efi_tables[i].table = __pa(efi.acpi20); + printf(" ACPI 2.0=0x%lx",tables->efi_tables[i].table); i++; } if (efi.acpi) { - efi_tables[i].guid = ACPI_TABLE_GUID; - efi_tables[i].table = __pa(efi.acpi); - printf(" ACPI=0x%lx",efi_tables[i].table); + tables->efi_tables[i].guid = ACPI_TABLE_GUID; + tables->efi_tables[i].table = __pa(efi.acpi); + printf(" ACPI=0x%lx",tables->efi_tables[i].table); i++; } if (efi.smbios) { - efi_tables[i].guid = SMBIOS_TABLE_GUID; - efi_tables[i].table = __pa(efi.smbios); - printf(" SMBIOS=0x%lx",efi_tables[i].table); + tables->efi_tables[i].guid = SMBIOS_TABLE_GUID; + tables->efi_tables[i].table = __pa(efi.smbios); + printf(" SMBIOS=0x%lx",tables->efi_tables[i].table); i++; } if (efi.hcdp) { - efi_tables[i].guid = HCDP_TABLE_GUID; - efi_tables[i].table = __pa(efi.hcdp); - printf(" HCDP=0x%lx",efi_tables[i].table); + tables->efi_tables[i].guid = HCDP_TABLE_GUID; + tables->efi_tables[i].table = __pa(efi.hcdp); + printf(" HCDP=0x%lx",tables->efi_tables[i].table); i++; } printf("\n"); } else { printf("DomainU EFI build up:"); - i = 1; - - if ((unsigned long)fw_mem + fw_mem_size - (unsigned long)cp >= - sizeof(struct fake_acpi_tables)) { - struct fake_acpi_tables *acpi_tables; - - acpi_tables = (void *)cp; - cp += sizeof(struct fake_acpi_tables); - dom_fw_fake_acpi(d, acpi_tables); - - efi_tables[i].guid = ACPI_20_TABLE_GUID; - efi_tables[i].table = dom_pa((unsigned long) acpi_tables); - printf(" ACPI 2.0=0x%lx",efi_tables[i].table); - i++; - } + + tables->efi_tables[i].guid = ACPI_20_TABLE_GUID; + tables->efi_tables[i].table = FW_ACPI_BASE_PADDR; + printf(" ACPI 2.0=0x%lx",tables->efi_tables[i].table); + i++; printf("\n"); } /* fill in the SAL system table: */ - memcpy(sal_systab->signature, "SST_", 4); - sal_systab->size = sizeof(*sal_systab); - sal_systab->sal_rev_minor = 1; - sal_systab->sal_rev_major = 0; - sal_systab->entry_count = 2; - - strcpy((char *)sal_systab->oem_id, "Xen/ia64"); - strcpy((char *)sal_systab->product_id, "Xen/ia64"); - - /* fill in an entry point: */ - sal_ed->type = SAL_DESC_ENTRY_POINT; - sal_ed->pal_proc = FW_HYPERCALL_PAL_CALL_PADDR + start_mpaddr; - dom_fw_pal_hypercall_patch (d, sal_ed->pal_proc); - sal_ed->sal_proc = FW_HYPERCALL_SAL_CALL_PADDR + start_mpaddr; - dom_fw_hypercall_patch (d, sal_ed->sal_proc, FW_HYPERCALL_SAL_CALL, 1); - sal_ed->gp = 0; // will be ignored + memcpy(tables->sal_systab.signature, "SST_", 4); + tables->sal_systab.size = sizeof(tables->sal_systab); + tables->sal_systab.sal_rev_minor = 1; + tables->sal_systab.sal_rev_major = 0; + tables->sal_systab.entry_count = 2; + + strcpy((char *)tables->sal_systab.oem_id, "Xen/ia64"); + strcpy((char *)tables->sal_systab.product_id, "Xen/ia64"); + + /* PAL entry point: */ + tables->sal_ed.type = SAL_DESC_ENTRY_POINT; + tables->sal_ed.pal_proc = FW_HYPERCALL_PAL_CALL_PADDR; + dom_fw_pal_hypercall_patch(d, tables->sal_ed.pal_proc, + hypercalls_imva); + /* SAL entry point. */ + tables->sal_ed.sal_proc = FW_HYPERCALL_SAL_CALL_PADDR; + dom_fw_hypercall_patch(d, tables->sal_ed.sal_proc, + FW_HYPERCALL_SAL_CALL, 1, hypercalls_imva); + tables->sal_ed.gp = 0; /* will be ignored */ /* Fill an AP wakeup descriptor. */ - sal_wakeup->type = SAL_DESC_AP_WAKEUP; - sal_wakeup->mechanism = IA64_SAL_AP_EXTERNAL_INT; - sal_wakeup->vector = XEN_SAL_BOOT_RENDEZ_VEC; + tables->sal_wakeup.type = SAL_DESC_AP_WAKEUP; + tables->sal_wakeup.mechanism = IA64_SAL_AP_EXTERNAL_INT; + tables->sal_wakeup.vector = XEN_SAL_BOOT_RENDEZ_VEC; /* Compute checksum. */ - for (cp = (char *) sal_systab; cp < (char *) efi_memmap; ++cp) + checksum = 0; + for (cp = (char *)&tables->sal_systab; + cp < (char *)&tables->fpswa_inf; + ++cp) checksum += *cp; - sal_systab->checksum = -checksum; + tables->sal_systab.checksum = -checksum; /* SAL return point. */ - d->arch.sal_return_addr = FW_HYPERCALL_SAL_RETURN_PADDR + start_mpaddr; - dom_fw_hypercall_patch (d, d->arch.sal_return_addr, - FW_HYPERCALL_SAL_RETURN, 0); + dom_fw_hypercall_patch(d, FW_HYPERCALL_SAL_RETURN_PADDR, + FW_HYPERCALL_SAL_RETURN, 0, hypercalls_imva); /* Fill in the FPSWA interface: */ - fpswa_inf->revision = fpswa_interface->revision; - dom_fpswa_hypercall_patch(d); - fpswa_inf->fpswa = (void *) FW_HYPERCALL_FPSWA_ENTRY_PADDR + start_mpaddr; + tables->fpswa_inf.revision = fpswa_interface->revision; + dom_fpswa_hypercall_patch(d, hypercalls_imva); + tables->fpswa_inf.fpswa = (void *)FW_HYPERCALL_FPSWA_ENTRY_PADDR; i = 0; /* Used by MAKE_MD */ - /* Create dom0/domu md entry for fw_mem area */ - MAKE_MD(EFI_ACPI_RECLAIM_MEMORY, EFI_MEMORY_WB | EFI_MEMORY_RUNTIME, - dom_pa((unsigned long)fw_mem), - dom_pa((unsigned long)fw_mem + fw_mem_size), 1); - - if (d == dom0) { - /* hypercall patches live here, masquerade as reserved PAL memory */ - MAKE_MD(EFI_PAL_CODE,EFI_MEMORY_WB|EFI_MEMORY_RUNTIME,HYPERCALL_START,HYPERCALL_END, 0); - - /* pass through the I/O port space */ - if (!running_on_sim) { - struct dom0_passthrough_arg arg; - arg.md = &efi_memmap[i]; - arg.i = &i; - arg.d = d; - arg.flags = ASSIGN_writable; - //XXX Is this needed? - efi_memmap_walk_type(EFI_RUNTIME_SERVICES_CODE, - dom_fw_dom0_passthrough, &arg); - // for ACPI table. - arg.flags = ASSIGN_readonly; - efi_memmap_walk_type(EFI_RUNTIME_SERVICES_DATA, - dom_fw_dom0_passthrough, &arg); - arg.flags = ASSIGN_writable; - efi_memmap_walk_type(EFI_ACPI_RECLAIM_MEMORY, - dom_fw_dom0_passthrough, &arg); - efi_memmap_walk_type(EFI_ACPI_MEMORY_NVS, - dom_fw_dom0_passthrough, &arg); - efi_memmap_walk_type(EFI_RESERVED_TYPE, - dom_fw_dom0_passthrough, &arg); - efi_memmap_walk_type(EFI_MEMORY_MAPPED_IO, - dom_fw_dom0_passthrough, &arg); - efi_memmap_walk_type(EFI_MEMORY_MAPPED_IO_PORT_SPACE, - dom_fw_dom0_passthrough, &arg); - efi_memmap_walk_type(EFI_CONVENTIONAL_MEMORY, - dom_fw_dom0_lowmem, &arg); - } - else MAKE_MD(EFI_RESERVED_TYPE,0,0,0,0); - } else { - /* hypercall patches live here, masquerade as reserved - PAL memory */ - MAKE_MD(EFI_PAL_CODE, EFI_MEMORY_WB | EFI_MEMORY_RUNTIME, - HYPERCALL_START, HYPERCALL_END, 1); + /* hypercall patches live here, masquerade as reserved PAL memory */ + MAKE_MD(EFI_PAL_CODE,EFI_MEMORY_WB|EFI_MEMORY_RUNTIME, + FW_HYPERCALL_BASE_PADDR, FW_HYPERCALL_END_PADDR); + + /* Create dom0/domu md entry for fw and cpi tables area. */ + MAKE_MD(EFI_ACPI_MEMORY_NVS, EFI_MEMORY_WB | EFI_MEMORY_RUNTIME, + FW_ACPI_BASE_PADDR, FW_ACPI_END_PADDR); + MAKE_MD(EFI_RUNTIME_SERVICES_DATA, EFI_MEMORY_WB | EFI_MEMORY_RUNTIME, + FW_TABLES_BASE_PADDR, FW_TABLES_END_PADDR); + + if (d != dom0 || running_on_sim) { + /* DomU (or hp-ski). + Create a continuous memory area. */ + /* Memory. */ + MAKE_MD(EFI_CONVENTIONAL_MEMORY, EFI_MEMORY_WB, + FW_END_PADDR, maxmem); + /* Create an entry for IO ports. */ MAKE_MD(EFI_MEMORY_MAPPED_IO_PORT_SPACE, EFI_MEMORY_UC, - IO_PORTS_PADDR, IO_PORTS_PADDR + IO_PORTS_SIZE, 1); - MAKE_MD(EFI_RESERVED_TYPE,0,0,0,0); - } - - // simple - // MAKE_MD(EFI_CONVENTIONAL_MEMORY, EFI_MEMORY_WB, - // HYPERCALL_END, maxmem, 0); - // is not good. Check overlap. - sort(efi_memmap, i, sizeof(efi_memory_desc_t), - efi_mdt_cmp, NULL); - - // find gap and fill it with conventional memory - num_mds = i; - for (j = 0; j < num_mds; j++) { - unsigned long end; - unsigned long next_start; - - md = &efi_memmap[j]; - end = md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT); - - next_start = maxmem; - if (j + 1 < num_mds) { - efi_memory_desc_t* next_md = &efi_memmap[j + 1]; - next_start = next_md->phys_addr; - BUG_ON(end > next_start); - if (end == next_md->phys_addr) - continue; - } - - // clip the range and align to PAGE_SIZE - // Avoid "legacy" low memory addresses and the - // HYPERCALL patch area. - if (end < HYPERCALL_END) - end = HYPERCALL_END; - if (next_start > maxmem) - next_start = maxmem; - end = PAGE_ALIGN(end); - next_start = next_start & PAGE_MASK; - if (end >= next_start) - continue; - - MAKE_MD(EFI_CONVENTIONAL_MEMORY, EFI_MEMORY_WB, - end, next_start, 0); - if (next_start >= maxmem) - break; - } - sort(efi_memmap, i, sizeof(efi_memory_desc_t), efi_mdt_cmp, NULL); - - bp->efi_systab = dom_pa((unsigned long) fw_mem); - bp->efi_memmap = dom_pa((unsigned long) efi_memmap); - BUG_ON(i > NUM_MEM_DESCS); - bp->efi_memmap_size = i * sizeof(efi_memory_desc_t); + IO_PORTS_PADDR, IO_PORTS_PADDR + IO_PORTS_SIZE); + + num_mds = i; + } + else { + /* Dom0. + We must preserve ACPI data from real machine, + as well as IO areas. */ + num_mds = complete_dom0_memmap(d, tables, maxmem, i); + } + + /* Display memmap. */ + for (i = 0 ; i < num_mds; i++) + print_md(&tables->efi_memmap[i]); + + /* Fill boot_param */ + bp->efi_systab = FW_FIELD_MPA(efi_systab); + bp->efi_memmap = FW_FIELD_MPA(efi_memmap); + bp->efi_memmap_size = num_mds * sizeof(efi_memory_desc_t); bp->efi_memdesc_size = sizeof(efi_memory_desc_t); bp->efi_memdesc_version = EFI_MEMDESC_VERSION; bp->command_line = 0; @@ -875,49 +867,44 @@ dom_fw_init (struct domain *d, struct ia bp->console_info.num_rows = 25; bp->console_info.orig_x = 0; bp->console_info.orig_y = 24; - bp->fpswa = dom_pa((unsigned long) fpswa_inf); - if (d == dom0) { - int j; - u64 addr; - - // dom0 doesn't need build_physmap_table() - // see arch_set_info_guest() - // instead we allocate pages manually. - for (j = 0; j < i; j++) { - md = &efi_memmap[j]; - if (md->phys_addr > maxmem) - break; - - if (md->type == EFI_LOADER_DATA || - md->type == EFI_PAL_CODE || - md->type == EFI_CONVENTIONAL_MEMORY) { - unsigned long start = md->phys_addr & PAGE_MASK; - unsigned long end = md->phys_addr + - (md->num_pages << EFI_PAGE_SHIFT); - - if (end == start) { - // md->num_pages = 0 is allowed. - end += PAGE_SIZE; - } - if (end > (max_page << PAGE_SHIFT)) - end = (max_page << PAGE_SHIFT); - - for (addr = start; addr < end; addr += PAGE_SIZE) { - assign_new_domain0_page(d, addr); - } - } - } - // Map low-memory holes & unmapped MMIO for legacy drivers - for (addr = 0; addr < 1*MB; addr += PAGE_SIZE) { - if (domain_page_mapped(d, addr)) - continue; - - if (efi_mmio(addr, PAGE_SIZE)) - assign_domain_mmio_page(d, addr, PAGE_SIZE); - } - } - for (i = 0 ; i < bp->efi_memmap_size/sizeof(efi_memory_desc_t) ; i++) { - md = efi_memmap + i; - print_md(md); - } -} + bp->fpswa = FW_FIELD_MPA(fpswa_inf); +} + +void dom_fw_setup(struct domain *d, unsigned long bp_mpa, unsigned long maxmem) +{ + struct ia64_boot_param *bp; + unsigned long imva_tables_base; + unsigned long imva_hypercall_base; + + BUILD_BUG_ON(sizeof(struct fw_tables) > + (FW_TABLES_END_PADDR - FW_TABLES_BASE_PADDR)); + + BUILD_BUG_ON(sizeof(struct fake_acpi_tables) > + (FW_ACPI_END_PADDR - FW_ACPI_BASE_PADDR)); + + /* Create page for hypercalls. */ + assign_new_domain_page_if_dom0(d, FW_HYPERCALL_BASE_PADDR); + imva_hypercall_base = (unsigned long)domain_mpa_to_imva + (d, FW_HYPERCALL_BASE_PADDR); + + /* Create page for acpi tables. */ + if (d != dom0) { + void *imva; + + assign_new_domain_page_if_dom0(d, FW_ACPI_BASE_PADDR); + imva = domain_mpa_to_imva (d, FW_ACPI_BASE_PADDR); + dom_fw_fake_acpi(d, (struct fake_acpi_tables *)imva); + } + + /* Create page for FW tables. */ + assign_new_domain_page_if_dom0(d, FW_TABLES_BASE_PADDR); + imva_tables_base = (unsigned long)domain_mpa_to_imva + (d, FW_TABLES_BASE_PADDR); + + /* Create page for boot_param. */ + assign_new_domain_page_if_dom0(d, bp_mpa); + bp = domain_mpa_to_imva(d, bp_mpa); + + dom_fw_init(d, bp, (struct fw_tables *)imva_tables_base, + imva_hypercall_base, maxmem); +} diff -r e01441c9a607 -r 50aea0ec406b xen/arch/ia64/xen/domain.c --- a/xen/arch/ia64/xen/domain.c Wed Aug 30 14:09:31 2006 -0500 +++ b/xen/arch/ia64/xen/domain.c Wed Aug 30 22:36:18 2006 +0100 @@ -46,7 +46,6 @@ #include <asm/regionreg.h> #include <asm/dom_fw.h> #include <asm/shadow.h> -#include <asm/privop_stat.h> unsigned long dom0_size = 512*1024*1024; unsigned long dom0_align = 64*1024*1024; @@ -111,6 +110,8 @@ void schedule_tail(struct vcpu *prev) if (VMX_DOMAIN(current)) { vmx_do_launch(current); + migrate_timer(¤t->arch.arch_vmx.vtm.vtm_timer, + current->processor); } else { ia64_set_iva(&ia64_ivt); ia64_set_pta(VHPT_ADDR | (1 << 8) | (VHPT_SIZE_LOG2 << 2) | @@ -121,6 +122,7 @@ void schedule_tail(struct vcpu *prev) shared_info->vcpu_info[current->vcpu_id].evtchn_upcall_mask; __ia64_per_cpu_var(current_psr_ic_addr) = (int *) (current->domain->arch.shared_info_va + XSI_PSR_IC_OFS); + migrate_timer(¤t->arch.hlt_timer, current->processor); } flush_vtlb_for_context_switch(current); } @@ -134,10 +136,18 @@ void context_switch(struct vcpu *prev, s __ia64_save_fpu(prev->arch._thread.fph); __ia64_load_fpu(next->arch._thread.fph); - if (VMX_DOMAIN(prev)) - vmx_save_state(prev); + if (VMX_DOMAIN(prev)) { + vmx_save_state(prev); + if (!VMX_DOMAIN(next)) { + /* VMX domains can change the physical cr.dcr. + * Restore default to prevent leakage. */ + ia64_setreg(_IA64_REG_CR_DCR, (IA64_DCR_DP | IA64_DCR_DK + | IA64_DCR_DX | IA64_DCR_DR | IA64_DCR_PP + | IA64_DCR_DA | IA64_DCR_DD | IA64_DCR_LC)); + } + } if (VMX_DOMAIN(next)) - vmx_load_state(next); + vmx_load_state(next); /*ia64_psr(ia64_task_regs(next))->dfh = !ia64_is_local_fpu_owner(next);*/ prev = ia64_switch_to(next); @@ -147,6 +157,8 @@ void context_switch(struct vcpu *prev, s if (VMX_DOMAIN(current)){ vmx_load_all_rr(current); + migrate_timer(¤t->arch.arch_vmx.vtm.vtm_timer, + current->processor); } else { struct domain *nd; extern char ia64_ivt; @@ -228,6 +240,12 @@ void startup_cpu_idle_loop(void) # error "XMAPPEDREGS_SHIFT doesn't match sizeof(mapped_regs_t)." #endif +void hlt_timer_fn(void *data) +{ + struct vcpu *v = data; + vcpu_unblock(v); +} + struct vcpu *alloc_vcpu_struct(struct domain *d, unsigned int vcpu_id) { struct vcpu *v; @@ -287,6 +305,10 @@ struct vcpu *alloc_vcpu_struct(struct do v->arch.breakimm = d->arch.breakimm; v->arch.last_processor = INVALID_PROCESSOR; } + if (!VMX_DOMAIN(v)){ + init_timer(&v->arch.hlt_timer, hlt_timer_fn, v, + first_cpu(cpu_online_map)); + } return v; } @@ -298,6 +320,7 @@ void relinquish_vcpu_resources(struct vc get_order_from_shift(XMAPPEDREGS_SHIFT)); v->arch.privregs = NULL; } + kill_timer(&v->arch.hlt_timer); } void free_vcpu_struct(struct vcpu *v) @@ -532,6 +555,9 @@ void domain_relinquish_resources(struct // relase page traversing d->arch.mm. relinquish_mm(d); + if (d->vcpu[0] && VMX_DOMAIN(d->vcpu[0])) + vmx_relinquish_guest_resources(d); + relinquish_memory(d, &d->xenpage_list); relinquish_memory(d, &d->page_list); @@ -591,7 +617,7 @@ domain_set_shared_info_va (unsigned long /* Transfer and clear the shadow bitmap in 1kB chunks for L1 cache. */ #define SHADOW_COPY_CHUNK (1024 / sizeof (unsigned long)) -int shadow_mode_control(struct domain *d, xen_domctl_shadow_ops_t *sc) +int shadow_mode_control(struct domain *d, xen_domctl_shadow_op_t *sc) { unsigned int op = sc->op; int rc = 0; @@ -716,6 +742,15 @@ int shadow_mode_control(struct domain *d } break; } + case XEN_DOMCTL_SHADOW_OP_GET_ALLOCATION: + sc->mb = 0; + break; + case XEN_DOMCTL_SHADOW_OP_SET_ALLOCATION: + if (sc->mb > 0) { + BUG(); + rc = -ENOMEM; + } + break; default: rc = -EINVAL; break; @@ -1082,13 +1117,15 @@ void machine_restart(char * __unused) while(1); } +extern void cpu_halt(void); + void machine_halt(void) { console_start_sync(); if (running_on_sim) printf ("machine_halt called. spinning...\n"); else - (*efi.reset_system)(EFI_RESET_SHUTDOWN,0,0,NULL); + cpu_halt(); while(1); } diff -r e01441c9a607 -r 50aea0ec406b xen/arch/ia64/xen/faults.c --- a/xen/arch/ia64/xen/faults.c Wed Aug 30 14:09:31 2006 -0500 +++ b/xen/arch/ia64/xen/faults.c Wed Aug 30 22:36:18 2006 +0100 @@ -13,6 +13,8 @@ #include <xen/smp.h> #include <asm/ptrace.h> #include <xen/delay.h> +#include <xen/perfc.h> +#include <xen/mm.h> #include <asm/system.h> #include <asm/processor.h> @@ -26,9 +28,9 @@ #include <asm/debugger.h> #include <asm/fpswa.h> #include <asm/bundle.h> -#include <asm/privop_stat.h> #include <asm/asm-xsi-offsets.h> #include <asm/shadow.h> +#include <asm/uaccess.h> extern void die_if_kernel(char *str, struct pt_regs *regs, long err); /* FIXME: where these declarations shold be there ? */ @@ -516,7 +518,8 @@ ia64_handle_break (unsigned long ifa, st debugger_trap_fatal(0 /* don't care */, regs); } #endif - else if (iim == d->arch.breakimm) { + else if (iim == d->arch.breakimm && + ia64_get_cpl(regs->cr_ipsr) == 2) { /* by default, do not continue */ v->arch.hypercall_continuation = 0; diff -r e01441c9a607 -r 50aea0ec406b xen/arch/ia64/xen/flushd.S --- a/xen/arch/ia64/xen/flushd.S Wed Aug 30 14:09:31 2006 -0500 +++ b/xen/arch/ia64/xen/flushd.S Wed Aug 30 22:36:18 2006 +0100 @@ -16,8 +16,9 @@ * * Flush cache. * - * Must deal with range from start to end-1 but nothing else (need to - * be careful not to touch addresses that may be unmapped). + * Must deal with range from start to end-1 but nothing else + * (need to be careful not to touch addresses that may be + * unmapped). * * Note: "in0" and "in1" are preserved for debugging purposes. */ @@ -37,7 +38,8 @@ GLOBAL_ENTRY(flush_dcache_range) ;; sub r8=r22,r23 // number of strides - 1 shl r24=r23,r20 // r24: addresses for "fc" = - // "start" rounded down to stride boundary + // "start" rounded down to stride + // boundary .save ar.lc,r3 mov r3=ar.lc // save ar.lc ;; @@ -49,7 +51,8 @@ GLOBAL_ENTRY(flush_dcache_range) * 32 byte aligned loop, even number of (actually 2) bundles */ .Loop: fc r24 // issuable on M0 only - add r24=r21,r24 // we flush "stride size" bytes per iteration + add r24=r21,r24 // we flush "stride size" bytes per + // iteration nop.i 0 br.cloop.sptk.few .Loop ;; diff -r e01441c9a607 -r 50aea0ec406b xen/arch/ia64/xen/fw_emul.c --- a/xen/arch/ia64/xen/fw_emul.c Wed Aug 30 14:09:31 2006 -0500 +++ b/xen/arch/ia64/xen/fw_emul.c Wed Aug 30 22:36:18 2006 +0100 @@ -28,6 +28,7 @@ #include "hpsim_ssc.h" #include <asm/vcpu.h> #include <asm/dom_fw.h> +#include <asm/uaccess.h> extern unsigned long running_on_sim; @@ -420,6 +421,141 @@ efi_emulate_get_time( } static efi_status_t +efi_emulate_get_variable( + unsigned long name_addr, unsigned long vendor_addr, + unsigned long attr_addr, unsigned long data_size_addr, + unsigned long data_addr, IA64FAULT *fault) +{ + unsigned long name, vendor, attr = 0, data_size, data; + struct page_info *name_page = NULL, *vendor_page = NULL, + *attr_page = NULL, *data_size_page = NULL, + *data_page = NULL; + efi_status_t status = 0; + + if (current->domain != dom0) + return EFI_UNSUPPORTED; + + name = efi_translate_domain_addr(name_addr, fault, &name_page); + if (*fault != IA64_NO_FAULT) + goto errout; + vendor = efi_translate_domain_addr(vendor_addr, fault, &vendor_page); + if (*fault != IA64_NO_FAULT) + goto errout; + data_size = efi_translate_domain_addr(data_size_addr, fault, + &data_size_page); + if (*fault != IA64_NO_FAULT) + goto errout; + data = efi_translate_domain_addr(data_addr, fault, &data_page); + if (*fault != IA64_NO_FAULT) + goto errout; + if (attr_addr) { + attr = efi_translate_domain_addr(attr_addr, fault, &attr_page); + if (*fault != IA64_NO_FAULT) + goto errout; + } + + status = (*efi.get_variable)((efi_char16_t *)name, + (efi_guid_t *)vendor, + (u32 *)attr, + (unsigned long *)data_size, + (void *)data); + +errout: + if (name_page != NULL) + put_page(name_page); + if (vendor_page != NULL) + put_page(vendor_page); + if (attr_page != NULL) + put_page(attr_page); + if (data_size_page != NULL) + put_page(data_size_page); + if (data_page != NULL) + put_page(data_page); + + return status; +} + +static efi_status_t +efi_emulate_get_next_variable( + unsigned long name_size_addr, unsigned long name_addr, + unsigned long vendor_addr, IA64FAULT *fault) +{ + unsigned long name_size, name, vendor; + struct page_info *name_size_page = NULL, *name_page = NULL, + *vendor_page = NULL; + efi_status_t status = 0; + + if (current->domain != dom0) + return EFI_UNSUPPORTED; + + name_size = efi_translate_domain_addr(name_size_addr, fault, + &name_size_page); + if (*fault != IA64_NO_FAULT) + goto errout; + name = efi_translate_domain_addr(name_addr, fault, &name_page); + if (*fault != IA64_NO_FAULT) + goto errout; + vendor = efi_translate_domain_addr(vendor_addr, fault, &vendor_page); + if (*fault != IA64_NO_FAULT) + goto errout; + + status = (*efi.get_next_variable)((unsigned long *)name_size, + (efi_char16_t *)name, + (efi_guid_t *)vendor); + +errout: + if (name_size_page != NULL) + put_page(name_size_page); + if (name_page != NULL) + put_page(name_page); + if (vendor_page != NULL) + put_page(vendor_page); + + return status; +} + +static efi_status_t +efi_emulate_set_variable( + unsigned long name_addr, unsigned long vendor_addr, + unsigned long attr, unsigned long data_size, + unsigned long data_addr, IA64FAULT *fault) +{ + unsigned long name, vendor, data; + struct page_info *name_page = NULL, *vendor_page = NULL, + *data_page = NULL; + efi_status_t status = 0; + + if (current->domain != dom0) + return EFI_UNSUPPORTED; + + name = efi_translate_domain_addr(name_addr, fault, &name_page); + if (*fault != IA64_NO_FAULT) + goto errout; + vendor = efi_translate_domain_addr(vendor_addr, fault, &vendor_page); + if (*fault != IA64_NO_FAULT) + goto errout; + data = efi_translate_domain_addr(data_addr, fault, &data_page); + if (*fault != IA64_NO_FAULT) + goto errout; + + status = (*efi.set_variable)((efi_char16_t *)name, + (efi_guid_t *)vendor, + attr, + data_size, + (void *)data); + +errout: + if (name_page != NULL) + put_page(name_page); + if (vendor_page != NULL) + put_page(vendor_page); + if (data_page != NULL) + put_page(data_page); + + return status; +} + +static efi_status_t efi_emulate_set_virtual_address_map( unsigned long memory_map_size, unsigned long descriptor_size, u32 descriptor_version, efi_memory_desc_t *virtual_map) @@ -527,6 +663,31 @@ efi_emulator (struct pt_regs *regs, IA64 vcpu_get_gr(v,33), fault); break; + case FW_HYPERCALL_EFI_GET_VARIABLE: + status = efi_emulate_get_variable ( + vcpu_get_gr(v,32), + vcpu_get_gr(v,33), + vcpu_get_gr(v,34), + vcpu_get_gr(v,35), + vcpu_get_gr(v,36), + fault); + break; + case FW_HYPERCALL_EFI_GET_NEXT_VARIABLE: + status = efi_emulate_get_next_variable ( + vcpu_get_gr(v,32), + vcpu_get_gr(v,33), + vcpu_get_gr(v,34), + fault); + break; + case FW_HYPERCALL_EFI_SET_VARIABLE: + status = efi_emulate_set_variable ( + vcpu_get_gr(v,32), + vcpu_get_gr(v,33), + vcpu_get_gr(v,34), + vcpu_get_gr(v,35), + vcpu_get_gr(v,36), + fault); + break; case FW_HYPERCALL_EFI_SET_VIRTUAL_ADDRESS_MAP: status = efi_emulate_set_virtual_address_map ( vcpu_get_gr(v,32), @@ -538,10 +699,6 @@ efi_emulator (struct pt_regs *regs, IA64 case FW_HYPERCALL_EFI_GET_WAKEUP_TIME: case FW_HYPERCALL_EFI_SET_WAKEUP_TIME: // FIXME: need fixes in efi.h from 2.6.9 - case FW_HYPERCALL_EFI_GET_VARIABLE: - // FIXME: need fixes in efi.h from 2.6.9 - case FW_HYPERCALL_EFI_GET_NEXT_VARIABLE: - case FW_HYPERCALL_EFI_SET_VARIABLE: case FW_HYPERCALL_EFI_GET_NEXT_HIGH_MONO_COUNT: // FIXME: need fixes in efi.h from 2.6.9 status = EFI_UNSUPPORTED; diff -r e01441c9a607 -r 50aea0ec406b xen/arch/ia64/xen/hypercall.c --- a/xen/arch/ia64/xen/hypercall.c Wed Aug 30 14:09:31 2006 -0500 +++ b/xen/arch/ia64/xen/hypercall.c Wed Aug 30 22:36:18 2006 +0100 @@ -11,6 +11,7 @@ #include <xen/hypercall.h> #include <xen/multicall.h> #include <xen/guest_access.h> +#include <xen/mm.h> #include <linux/efi.h> /* FOR EFI_UNIMPLEMENTED */ #include <asm/sal.h> /* FOR struct ia64_sal_retval */ @@ -29,45 +30,45 @@ #include <xen/domain.h> #include <public/callback.h> #include <xen/event.h> -#include <asm/privop_stat.h> +#include <xen/perfc.h> static long do_physdev_op_compat(XEN_GUEST_HANDLE(physdev_op_t) uop); static long do_physdev_op(int cmd, XEN_GUEST_HANDLE(void) arg); static long do_callback_op(int cmd, XEN_GUEST_HANDLE(void) arg); -hypercall_t ia64_hypercall_table[] = - { - (hypercall_t)do_ni_hypercall, /* do_set_trap_table */ /* 0 */ +const hypercall_t ia64_hypercall_table[NR_hypercalls] = +{ + (hypercall_t)do_ni_hypercall, /* do_set_trap_table *//* 0 */ (hypercall_t)do_ni_hypercall, /* do_mmu_update */ (hypercall_t)do_ni_hypercall, /* do_set_gdt */ (hypercall_t)do_ni_hypercall, /* do_stack_switch */ (hypercall_t)do_ni_hypercall, /* do_set_callbacks */ - (hypercall_t)do_ni_hypercall, /* do_fpu_taskswitch */ /* 5 */ + (hypercall_t)do_ni_hypercall, /* do_fpu_taskswitch *//* 5 */ (hypercall_t)do_sched_op_compat, (hypercall_t)do_ni_hypercall, (hypercall_t)do_ni_hypercall, /* do_set_debugreg */ (hypercall_t)do_ni_hypercall, /* do_get_debugreg */ - (hypercall_t)do_ni_hypercall, /* do_update_descriptor */ /* 10 */ + (hypercall_t)do_ni_hypercall, /* do_update_descriptor * 10 */ (hypercall_t)do_ni_hypercall, /* do_ni_hypercall */ (hypercall_t)do_memory_op, (hypercall_t)do_multicall, (hypercall_t)do_ni_hypercall, /* do_update_va_mapping */ - (hypercall_t)do_ni_hypercall, /* do_set_timer_op */ /* 15 */ + (hypercall_t)do_ni_hypercall, /* do_set_timer_op */ /* 15 */ (hypercall_t)do_event_channel_op_compat, (hypercall_t)do_xen_version, (hypercall_t)do_console_io, (hypercall_t)do_physdev_op_compat, - (hypercall_t)do_grant_table_op, /* 20 */ + (hypercall_t)do_grant_table_op, /* 20 */ (hypercall_t)do_ni_hypercall, /* do_vm_assist */ - (hypercall_t)do_ni_hypercall, /* do_update_va_mapping_otherdomain */ + (hypercall_t)do_ni_hypercall, /* do_update_va_mapping_othe */ (hypercall_t)do_ni_hypercall, /* (x86 only) */ (hypercall_t)do_ni_hypercall, /* do_vcpu_op */ - (hypercall_t)do_ni_hypercall, /* (x86_64 only) */ /* 25 */ + (hypercall_t)do_ni_hypercall, /* (x86_64 only) */ /* 25 */ (hypercall_t)do_ni_hypercall, /* do_mmuext_op */ (hypercall_t)do_ni_hypercall, /* do_acm_op */ (hypercall_t)do_ni_hypercall, /* do_nmi_op */ (hypercall_t)do_sched_op, - (hypercall_t)do_callback_op, /* */ /* 30 */ + (hypercall_t)do_callback_op, /* */ /* 30 */ (hypercall_t)do_ni_hypercall, /* */ (hypercall_t)do_event_channel_op, (hypercall_t)do_physdev_op, @@ -77,33 +78,52 @@ hypercall_t ia64_hypercall_table[] = (hypercall_t)do_ni_hypercall, /* */ (hypercall_t)do_ni_hypercall, /* */ (hypercall_t)do_ni_hypercall, /* */ - (hypercall_t)do_ni_hypercall, /* */ /* 40 */ - (hypercall_t)do_ni_hypercall, /* */ - (hypercall_t)do_ni_hypercall, /* */ - (hypercall_t)do_ni_hypercall, /* */ - (hypercall_t)do_ni_hypercall, /* */ - (hypercall_t)do_ni_hypercall, /* */ /* 45 */ - (hypercall_t)do_ni_hypercall, /* */ - (hypercall_t)do_ni_hypercall, /* */ - (hypercall_t)do_dom0vp_op, /* dom0vp_op */ + (hypercall_t)do_ni_hypercall, /* */ /* 40 */ + (hypercall_t)do_ni_hypercall, /* */ + (hypercall_t)do_ni_hypercall, /* */ + (hypercall_t)do_ni_hypercall, /* */ + (hypercall_t)do_ni_hypercall, /* */ + (hypercall_t)do_ni_hypercall, /* */ /* 45 */ + (hypercall_t)do_ni_hypercall, /* */ + (hypercall_t)do_ni_hypercall, /* */ + (hypercall_t)do_dom0vp_op, /* dom0vp_op */ (hypercall_t)do_ni_hypercall, /* arch_1 */ - (hypercall_t)do_ni_hypercall, /* arch_2 */ /* 50 */ + (hypercall_t)do_ni_hypercall, /* arch_2 */ /* 50 */ (hypercall_t)do_ni_hypercall, /* arch_3 */ (hypercall_t)do_ni_hypercall, /* arch_4 */ (hypercall_t)do_ni_hypercall, /* arch_5 */ (hypercall_t)do_ni_hypercall, /* arch_6 */ - (hypercall_t)do_ni_hypercall /* arch_7 */ /* 55 */ - }; - -uint32_t nr_hypercalls = - sizeof(ia64_hypercall_table) / sizeof(hypercall_t); + (hypercall_t)do_ni_hypercall, /* arch_7 */ /* 55 */ + (hypercall_t)do_ni_hypercall, + (hypercall_t)do_ni_hypercall, + (hypercall_t)do_ni_hypercall, + (hypercall_t)do_ni_hypercall, + (hypercall_t)do_ni_hypercall, /* 60 */ + (hypercall_t)do_ni_hypercall, + (hypercall_t)do_ni_hypercall, + (hypercall_t)do_ni_hypercall +}; static IA64FAULT xen_hypercall (struct pt_regs *regs) { uint32_t cmd = (uint32_t)regs->r2; - - if (cmd < nr_hypercalls) + struct vcpu *v = current; + + if (cmd == __HYPERVISOR_grant_table_op) { + XEN_GUEST_HANDLE(void) uop; + + v->arch.hypercall_param.va = regs->r15; + v->arch.hypercall_param.pa1 = regs->r17; + v->arch.hypercall_param.pa2 = regs->r18; + set_xen_guest_handle(uop, (void *)regs->r15); + regs->r8 = do_grant_table_op(regs->r14, uop, regs->r16); + v->arch.hypercall_param.va = 0; + return IA64_NO_FAULT; + } + + if (cmd < NR_hypercalls) { + perfc_incra(hypercalls, cmd); regs->r8 = (*ia64_hypercall_table[cmd])( regs->r14, regs->r15, @@ -111,12 +131,11 @@ xen_hypercall (struct pt_regs *regs) regs->r17, regs->r18, regs->r19); - else + } else regs->r8 = -ENOSYS; return IA64_NO_FAULT; } - static void fw_hypercall_ipi (struct pt_regs *regs) @@ -153,7 +172,7 @@ fw_hypercall_ipi (struct pt_regs *regs) vcpu_init_regs (targ); vcpu_regs (targ)->cr_iip = d->arch.sal_data->boot_rdv_ip; vcpu_regs (targ)->r1 = d->arch.sal_data->boot_rdv_r1; - vcpu_regs (targ)->b0 = d->arch.sal_return_addr; + vcpu_regs (targ)->b0 = FW_HYPERCALL_SAL_RETURN_PADDR; if (test_and_clear_bit(_VCPUF_down, &targ->vcpu_flags)) { @@ -217,7 +236,12 @@ fw_hypercall (struct pt_regs *regs) } else { perfc_incrc(pal_halt_light); - do_sched_op_compat(SCHEDOP_yield, 0); + migrate_timer(&v->arch.hlt_timer, + v->processor); + set_timer(&v->arch.hlt_timer, + vcpu_get_next_timer_ns(v)); + do_sched_op_compat(SCHEDOP_block, 0); + stop_timer(&v->arch.hlt_timer); } regs->r8 = 0; regs->r9 = 0; @@ -276,52 +300,10 @@ fw_hypercall (struct pt_regs *regs) return IA64_NO_FAULT; } -/* opt_unsafe_hypercall: If true, unsafe debugging hypercalls are allowed. - These can create security hole. */ -static int opt_unsafe_hypercall = 0; -boolean_param("unsafe_hypercall", opt_unsafe_hypercall); - IA64FAULT ia64_hypercall (struct pt_regs *regs) { - struct vcpu *v = current; unsigned long index = regs->r2; - int privlvl = (regs->cr_ipsr & IA64_PSR_CPL) >> IA64_PSR_CPL0_BIT; - - if (index >= FW_HYPERCALL_FIRST_USER) { - /* Note: user hypercalls are not safe, since Xen doesn't - check memory access privilege: Xen does not deny reading - or writing to kernel memory. */ - if (!opt_unsafe_hypercall) { - printf("user xen/ia64 hypercalls disabled\n"); - regs->r8 = -1; - } - else switch (index) { - case 0xffff: - regs->r8 = dump_privop_counts_to_user( - (char *) vcpu_get_gr(v,32), - (int) vcpu_get_gr(v,33)); - break; - case 0xfffe: - regs->r8 = zero_privop_counts_to_user( - (char *) vcpu_get_gr(v,32), - (int) vcpu_get_gr(v,33)); - break; - default: - printf("unknown user xen/ia64 hypercall %lx\n", index); - regs->r8 = do_ni_hypercall(); - } - return IA64_NO_FAULT; - } - - /* Hypercalls are only allowed by kernel. - Kernel checks memory accesses. */ - if (VMX_DOMAIN(v) ? (privlvl != 0) : (privlvl != 2)) { - /* FIXME: Return a better error value ? - Reflection ? Illegal operation ? */ - regs->r8 = -1; - return IA64_NO_FAULT; - } if (index >= FW_HYPERCALL_FIRST_ARCH) return fw_hypercall (regs); diff -r e01441c9a607 -r 50aea0ec406b xen/arch/ia64/xen/hyperprivop.S --- a/xen/arch/ia64/xen/hyperprivop.S Wed Aug 30 14:09:31 2006 -0500 +++ b/xen/arch/ia64/xen/hyperprivop.S Wed Aug 30 22:36:18 2006 +0100 @@ -18,7 +18,8 @@ #define _PAGE_PPN_MASK 0x0003fffffffff000 //asm/pgtable.h doesn't do assembly -#define PAGE_PHYS 0x0010000000000761 //__pgprot(__DIRTY_BITS|_PAGE_PL_2|_PAGE_AR_RWX) +#define PAGE_PHYS 0x0010000000000761 //__pgprot(__DIRTY_BITS| + // _PAGE_PL_2|_PAGE_AR_RWX) #define _PAGE_PL_2 (2<<7) #if 1 // change to 0 to turn off all fast paths @@ -32,10 +33,10 @@ //#define FAST_TICK // mostly working (unat problems) but default off for now //#define FAST_TLB_MISS_REFLECT // mostly working but default off for now -# undef FAST_ITC //XXX TODO fast_itc doesn't suport dom0 vp yet. +# undef FAST_ITC //XXX TODO fast_itc doesn't support dom0 vp yet # define FAST_BREAK -# undef FAST_ACCESS_REFLECT //XXX TODO fast_access_reflect - // doesn't support dom0 vp yet. +# undef FAST_ACCESS_REFLECT //XXX TODO fast_access_reflect + // doesn't support dom0 vp yet. # define FAST_RFI # define FAST_SSM_I # define FAST_PTC_GA @@ -104,79 +105,100 @@ 1: // when we get to here r20=~=interrup 1: // when we get to here r20=~=interrupts pending // Check pending event indication (p7) movl r20=THIS_CPU(current_psr_i_addr);; -(p7) ld8 r20=[r20];; -(p7) adds r20=-1,r20;; /* evtchn_upcall_pending */ -(p7) ld1 r20=[r20];; +(p7) ld8 r20=[r20] + ;; +(p7) adds r20=-1,r20 // evtchn_upcall_pending + ;; +(p7) ld1 r20=[r20] + ;; // HYPERPRIVOP_RFI? cmp.eq p7,p6=HYPERPRIVOP_RFI,r17 -(p7) br.sptk.many hyper_rfi;; +(p7) br.sptk.many hyper_rfi + ;; // HYPERPRIVOP_GET_IVR? cmp.eq p7,p6=HYPERPRIVOP_GET_IVR,r17 -(p7) br.sptk.many hyper_get_ivr;; +(p7) br.sptk.many hyper_get_ivr + ;; cmp.ne p7,p0=r20,r0 -(p7) br.spnt.many dispatch_break_fault ;; +(p7) br.spnt.many dispatch_break_fault + ;; // HYPERPRIVOP_COVER? cmp.eq p7,p6=HYPERPRIVOP_COVER,r17 -(p7) br.sptk.many hyper_cover;; +(p7) br.sptk.many hyper_cover + ;; // HYPERPRIVOP_SSM_DT? cmp.eq p7,p6=HYPERPRIVOP_SSM_DT,r17 -(p7) br.sptk.many hyper_ssm_dt;; +(p7) br.sptk.many hyper_ssm_dt + ;; // HYPERPRIVOP_RSM_DT? cmp.eq p7,p6=HYPERPRIVOP_RSM_DT,r17 -(p7) br.sptk.many hyper_rsm_dt;; +(p7) br.sptk.many hyper_rsm_dt + ;; // HYPERPRIVOP_GET_TPR? cmp.eq p7,p6=HYPERPRIVOP_GET_TPR,r17 -(p7) br.sptk.many hyper_get_tpr;; +(p7) br.sptk.many hyper_get_tpr + ;; // HYPERPRIVOP_SET_TPR? cmp.eq p7,p6=HYPERPRIVOP_SET_TPR,r17 -(p7) br.sptk.many hyper_set_tpr;; +(p7) br.sptk.many hyper_set_tpr + ;; // HYPERPRIVOP_EOI? cmp.eq p7,p6=HYPERPRIVOP_EOI,r17 -(p7) br.sptk.many hyper_eoi;; +(p7) br.sptk.many hyper_eoi + ;; // HYPERPRIVOP_SET_ITM? cmp.eq p7,p6=HYPERPRIVOP_SET_ITM,r17 -(p7) br.sptk.many hyper_set_itm;; +(p7) br.sptk.many hyper_set_itm + ;; // HYPERPRIVOP_SET_RR? cmp.eq p7,p6=HYPERPRIVOP_SET_RR,r17 -(p7) br.sptk.many hyper_set_rr;; +(p7) br.sptk.many hyper_set_rr + ;; // HYPERPRIVOP_GET_RR? cmp.eq p7,p6=HYPERPRIVOP_GET_RR,r17 -(p7) br.sptk.many hyper_get_rr;; +(p7) br.sptk.many hyper_get_rr + ;; // HYPERPRIVOP_PTC_GA? cmp.eq p7,p6=HYPERPRIVOP_PTC_GA,r17 -(p7) br.sptk.many hyper_ptc_ga;; +(p7) br.sptk.many hyper_ptc_ga + ;; // HYPERPRIVOP_ITC_D? cmp.eq p7,p6=HYPERPRIVOP_ITC_D,r17 -(p7) br.sptk.many hyper_itc_d;; +(p7) br.sptk.many hyper_itc_d + ;; // HYPERPRIVOP_ITC_I? cmp.eq p7,p6=HYPERPRIVOP_ITC_I,r17 -(p7) br.sptk.many hyper_itc_i;; +(p7) br.sptk.many hyper_itc_i + ;; // HYPERPRIVOP_THASH? cmp.eq p7,p6=HYPERPRIVOP_THASH,r17 -(p7) br.sptk.many hyper_thash;; +(p7) br.sptk.many hyper_thash + ;; // HYPERPRIVOP_SET_KR? cmp.eq p7,p6=HYPERPRIVOP_SET_KR,r17 -(p7) br.sptk.many hyper_set_kr;; +(p7) br.sptk.many hyper_set_kr + ;; // if not one of the above, give up for now and do it the slow way - br.sptk.many dispatch_break_fault ;; + br.sptk.many dispatch_break_fault + ;; END(fast_hyperprivop) // give up for now if: ipsr.be==1, ipsr.pp==1 @@ -701,9 +723,9 @@ ENTRY(fast_reflect) .mem.offset 0,0; st8.spill [r2]=r30,16; .mem.offset 8,0; st8.spill [r3]=r31,16 ;; #ifdef HANDLE_AR_UNAT - // r16~r23 are preserved regsin bank0 regs, we need to restore them, - // r24~r31 are scratch regs, we don't need to handle NaT bit, - // because OS handler must assign it before access it + // r16~r23 are preserved regs in bank0 regs, we need to restore them, + // r24~r31 are scratch regs, we don't need to handle NaT bit, + // because OS handler must assign it before access it ld8 r16=[r2],16; ld8 r17=[r3],16;; ld8 r18=[r2],16; @@ -1114,7 +1136,8 @@ just_do_rfi: (p7) st4 [r18]=r19;; (p6) st4 [r18]=r0;; // force on psr.ic, i, dt, rt, it, bn - movl r20=(IA64_PSR_I|IA64_PSR_IC|IA64_PSR_DT|IA64_PSR_RT|IA64_PSR_IT|IA64_PSR_BN) + movl r20=(IA64_PSR_I|IA64_PSR_IC|IA64_PSR_DT|IA64_PSR_RT| \ + IA64_PSR_IT|IA64_PSR_BN) ;; or r21=r21,r20 ;; diff -r e01441c9a607 -r 50aea0ec406b xen/arch/ia64/xen/irq.c --- a/xen/arch/ia64/xen/irq.c Wed Aug 30 14:09:31 2006 -0500 +++ b/xen/arch/ia64/xen/irq.c Wed Aug 30 22:36:18 2006 +0100 @@ -40,7 +40,6 @@ #include <asm/smp.h> #include <asm/system.h> #include <asm/bitops.h> -#include <asm/uaccess.h> #include <asm/pgalloc.h> #include <asm/delay.h> #include <xen/irq.h> @@ -236,9 +235,6 @@ int setup_vector(unsigned int irq, struc struct irqaction *old, **p; irq_desc_t *desc = irq_descp(irq); - printf ("setup_vector(%d): handler=%p, flags=%x\n", - irq, desc->handler, desc->status); - /* * The following block of code has to be executed atomically */ diff -r e01441c9a607 -r 50aea0ec406b xen/arch/ia64/xen/ivt.S --- a/xen/arch/ia64/xen/ivt.S Wed Aug 30 14:09:31 2006 -0500 +++ b/xen/arch/ia64/xen/ivt.S Wed Aug 30 22:36:18 2006 +0100 @@ -15,7 +15,8 @@ * Fenghua Yu <fenghua.yu@xxxxxxxxx> * * 00/08/23 Asit Mallick <asit.k.mallick@xxxxxxxxx> TLB handling for SMP - * 00/12/20 David Mosberger-Tang <davidm@xxxxxxxxxx> DTLB/ITLB handler now uses virtual PT. + * 00/12/20 David Mosberger-Tang <davidm@xxxxxxxxxx> DTLB/ITLB handler now + * uses virtual PT. */ /* * This file defines the interruption vector table used by the CPU. @@ -69,10 +70,14 @@ #if 0 /* - * This lets you track the last eight faults that occurred on the CPU. Make sure ar.k2 isn't - * needed for something else before enabling this... + * This lets you track the last eight faults that occurred on the CPU. + * Make sure ar.k2 isn't needed for something else before enabling this... */ -# define DBG_FAULT(i) mov r16=ar.k2;; shl r16=r16,8;; add r16=(i),r16;;mov ar.k2=r16 +# define DBG_FAULT(i) \ + mov r16=ar.k2;; \ + shl r16=r16,8;; \ + add r16=(i),r16;; \ + mov ar.k2=r16 #else # define DBG_FAULT(i) #endif @@ -80,18 +85,18 @@ #define MINSTATE_VIRT /* needed by minstate.h */ #include "minstate.h" -#define FAULT(n) \ - mov r19=n; /* prepare to save predicates */ \ - mov r31=pr; \ +#define FAULT(n) \ + mov r19=n; /* prepare to save predicates */ \ + mov r31=pr; \ br.sptk.many dispatch_to_fault_handler -#define FAULT_OR_REFLECT(n) \ - mov r20=cr.ipsr; \ - mov r19=n; /* prepare to save predicates */ \ - mov r31=pr;; \ - extr.u r20=r20,IA64_PSR_CPL0_BIT,2;; \ - cmp.ne p6,p0=r0,r20; /* cpl != 0?*/ \ -(p6) br.dptk.many dispatch_reflection; \ +#define FAULT_OR_REFLECT(n) \ + mov r20=cr.ipsr; \ + mov r19=n; /* prepare to save predicates */ \ + mov r31=pr;; \ + extr.u r20=r20,IA64_PSR_CPL0_BIT,2;; \ + cmp.ne p6,p0=r0,r20; /* cpl != 0?*/ \ +(p6) br.dptk.many dispatch_reflection; \ br.sptk.few dispatch_to_fault_handler .section .text.ivt,"ax" @@ -99,7 +104,7 @@ .align 32768 // align on 32KB boundary .global ia64_ivt ia64_ivt: -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x0000 Entry 0 (size 64 bundles) VHPT Translation (8,20,47) ENTRY(vhpt_miss) DBG_FAULT(0) @@ -107,33 +112,34 @@ ENTRY(vhpt_miss) FAULT(0) #else /* - * The VHPT vector is invoked when the TLB entry for the virtual page table - * is missing. This happens only as a result of a previous - * (the "original") TLB miss, which may either be caused by an instruction - * fetch or a data access (or non-access). + * The VHPT vector is invoked when the TLB entry for the virtual + * page table is missing. This happens only as a result of a + * previous (the "original") TLB miss, which may either be caused + * by an instruction fetch or a data access (or non-access). * - * What we do here is normal TLB miss handing for the _original_ miss, followed - * by inserting the TLB entry for the virtual page table page that the VHPT - * walker was attempting to access. The latter gets inserted as long - * as both L1 and L2 have valid mappings for the faulting address. - * The TLB entry for the original miss gets inserted only if - * the L3 entry indicates that the page is present. + * What we do here is normal TLB miss handing for the _original_ + * miss, followed by inserting the TLB entry for the virtual page + * table page that the VHPT walker was attempting to access. The + * latter gets inserted as long as both L1 and L2 have valid + * mappings for the faulting address. The TLB entry for the + * original miss gets inserted only if the L3 entry indicates + * that the page is present. * * do_page_fault gets invoked in the following cases: * - the faulting virtual address uses unimplemented address bits * - the faulting virtual address has no L1, L2, or L3 mapping */ - mov r16=cr.ifa // get address that caused the TLB miss + mov r16=cr.ifa // get address that caused the TLB miss #ifdef CONFIG_HUGETLB_PAGE movl r18=PAGE_SHIFT mov r25=cr.itir #endif ;; - rsm psr.dt // use physical addressing for data - mov r31=pr // save the predicate registers - mov r19=IA64_KR(PT_BASE) // get page table base address - shl r21=r16,3 // shift bit 60 into sign bit - shr.u r17=r16,61 // get the region number into r17 + rsm psr.dt // use physical addressing for data + mov r31=pr // save the predicate registers + mov r19=IA64_KR(PT_BASE) // get page table base address + shl r21=r16,3 // shift bit 60 into sign bit + shr.u r17=r16,61 // get the region number into r17 ;; shr r22=r21,3 #ifdef CONFIG_HUGETLB_PAGE @@ -146,56 +152,68 @@ ENTRY(vhpt_miss) (p8) shr r22=r22,r27 #endif ;; - cmp.eq p6,p7=5,r17 // is IFA pointing into to region 5? - shr.u r18=r22,PGDIR_SHIFT // get bits 33-63 of the faulting address - ;; -(p7) dep r17=r17,r19,(PAGE_SHIFT-3),3 // put region number bits in place + cmp.eq p6,p7=5,r17 // is IFA pointing into to region 5? + shr.u r18=r22,PGDIR_SHIFT // get bits 33-63 of faulting address + ;; +(p7) dep r17=r17,r19,(PAGE_SHIFT-3),3 // put region number bits in place srlz.d - LOAD_PHYSICAL(p6, r19, swapper_pg_dir) // region 5 is rooted at swapper_pg_dir + LOAD_PHYSICAL(p6, r19, swapper_pg_dir) // region 5 is rooted at + // swapper_pg_dir .pred.rel "mutex", p6, p7 (p6) shr.u r21=r21,PGDIR_SHIFT+PAGE_SHIFT (p7) shr.u r21=r21,PGDIR_SHIFT+PAGE_SHIFT-3 ;; (p6) dep r17=r18,r19,3,(PAGE_SHIFT-3) // r17=PTA + IFA(33,42)*8 -(p7) dep r17=r18,r17,3,(PAGE_SHIFT-6) // r17=PTA + (((IFA(61,63) << 7) | IFA(33,39))*8) - cmp.eq p7,p6=0,r21 // unused address bits all zeroes? +(p7) dep r17=r18,r17,3,(PAGE_SHIFT-6) // r17=PTA + + // (((IFA(61,63) << 7) | + // IFA(33,39))*8) + cmp.eq p7,p6=0,r21 // unused address bits all zero? shr.u r18=r22,PMD_SHIFT // shift L2 index into position ;; ld8 r17=[r17] // fetch the L1 entry (may be 0) ;; (p7) cmp.eq p6,p7=r17,r0 // was L1 entry NULL? - dep r17=r18,r17,3,(PAGE_SHIFT-3) // compute address of L2 page table entry + dep r17=r18,r17,3,(PAGE_SHIFT-3) // compute address of L2 page + // table entry ;; (p7) ld8 r20=[r17] // fetch the L2 entry (may be 0) shr.u r19=r22,PAGE_SHIFT // shift L3 index into position ;; (p7) cmp.eq.or.andcm p6,p7=r20,r0 // was L2 entry NULL? - dep r21=r19,r20,3,(PAGE_SHIFT-3) // compute address of L3 page table entry + dep r21=r19,r20,3,(PAGE_SHIFT-3) // compute address of L3 page + // table entry ;; (p7) ld8 r18=[r21] // read the L3 PTE - mov r19=cr.isr // cr.isr bit 0 tells us if this is an insn miss + mov r19=cr.isr // cr.isr bit 0 tells us if + // this is an insn miss ;; (p7) tbit.z p6,p7=r18,_PAGE_P_BIT // page present bit cleared? - mov r22=cr.iha // get the VHPT address that caused the TLB miss + mov r22=cr.iha // get the VHPT address that + // caused the TLB miss ;; // avoid RAW on p7 -(p7) tbit.nz.unc p10,p11=r19,32 // is it an instruction TLB miss? - dep r23=0,r20,0,PAGE_SHIFT // clear low bits to get page address - ;; -(p10) itc.i r18 // insert the instruction TLB entry +(p7) tbit.nz.unc p10,p11=r19,32 // is it an instruction TLB + // miss? + dep r23=0,r20,0,PAGE_SHIFT // clear low bits to get page + // address + ;; +(p10) itc.i r18 // insert the instruction TLB + // entry (p11) itc.d r18 // insert the data TLB entry -(p6) br.cond.spnt.many page_fault // handle bad address/page not present (page fault) +(p6) br.cond.spnt.many page_fault // handle bad address/page not + // present (page fault) mov cr.ifa=r22 #ifdef CONFIG_HUGETLB_PAGE -(p8) mov cr.itir=r25 // change to default page-size for VHPT -#endif - - /* - * Now compute and insert the TLB entry for the virtual page table. We never - * execute in a page table page so there is no need to set the exception deferral - * bit. +(p8) mov cr.itir=r25 // change to default page-size + // for VHPT +#endif + + /* + * Now compute and insert the TLB entry for the virtual page table. + * We never execute in a page table page so there is no need to set + * the exception deferral bit. */ adds r24=__DIRTY_BITS_NO_ED|_PAGE_PL_0|_PAGE_AR_RW,r23 ;; @@ -203,15 +221,15 @@ ENTRY(vhpt_miss) ;; #ifdef CONFIG_SMP /* - * Tell the assemblers dependency-violation checker that the above "itc" instructions - * cannot possibly affect the following loads: + * Tell the assemblers dependency-violation checker that the above + * "itc" instructions cannot possibly affect the following loads: */ dv_serialize_data /* - * Re-check L2 and L3 pagetable. If they changed, we may have received a ptc.g - * between reading the pagetable and the "itc". If so, flush the entry we - * inserted and retry. + * Re-check L2 and L3 pagetable. If they changed, we may have + * received a ptc.g between reading the pagetable and the "itc". + * If so, flush the entry we inserted and retry. */ ld8 r25=[r21] // read L3 PTE again ld8 r26=[r17] // read L2 entry again @@ -231,7 +249,7 @@ END(vhpt_miss) END(vhpt_miss) .org ia64_ivt+0x400 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x0400 Entry 1 (size 64 bundles) ITLB (21) ENTRY(itlb_miss) DBG_FAULT(1) @@ -266,7 +284,8 @@ ENTRY(itlb_miss) mov r31=pr // save predicates .itlb_fault: mov r17=cr.iha // get virtual address of L3 PTE - movl r30=1f // load nested fault continuation point + movl r30=1f // load nested fault + // continuation point ;; 1: ld8 r18=[r17] // read L3 PTE ;; @@ -278,13 +297,13 @@ 1: ld8 r18=[r17] // read L3 PTE ;; #ifdef CONFIG_SMP /* - * Tell the assemblers dependency-violation checker that the above "itc" instructions - * cannot possibly affect the following loads: + * Tell the assemblers dependency-violation checker that the above + * "itc" instructions cannot possibly affect the following loads: */ dv_serialize_data - ld8 r19=[r17] // read L3 PTE again and see if same - mov r20=PAGE_SHIFT<<2 // setup page size for purge + ld8 r19=[r17] // read L3 PTE again and see if same + mov r20=PAGE_SHIFT<<2 // setup page size for purge ;; cmp.ne p7,p0=r18,r19 ;; @@ -295,26 +314,25 @@ END(itlb_miss) END(itlb_miss) .org ia64_ivt+0x0800 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x0800 Entry 2 (size 64 bundles) DTLB (9,48) ENTRY(dtlb_miss) DBG_FAULT(2) #ifdef XEN - mov r16=cr.ifa // get virtual address + mov r16=cr.ifa // get virtual address mov r31=pr ;; extr.u r17=r16,59,5 ;; - /* If address belongs to VMM, go to alt tlb handler */ - cmp.eq p6,p0=0x1e,r17 + cmp.eq p6,p0=0x1e,r17 // if the address belongs to VMM, go + // to the alternate tlb handler (p6) br.cond.spnt late_alt_dtlb_miss ;; cmp.eq p6,p0=0x1d,r17 (p6) br.cond.spnt late_alt_dtlb_miss ;; #if VHPT_ENABLED - // XXX TODO optimization - mov r30=cr.ipsr + mov r30=cr.ipsr // XXX TODO optimization mov r28=cr.iip mov r17=cr.isr ;; @@ -324,15 +342,14 @@ ENTRY(dtlb_miss) cmp.ne p6, p0 = r0, r18 // cpl == 0? (p6) br.cond.sptk 2f - // is speculation bit on? - tbit.nz p7,p0=r17,IA64_ISR_SP_BIT + tbit.nz p7,p0=r17,IA64_ISR_SP_BIT // is speculation bit on? ;; (p7) br.cond.spnt 2f - // Is the faulted iip in vmm area? - // check [59:58] bit - // 00, 11: guest - // 01, 10: vmm + // Is the faulted iip in the vmm area? + // -- check [59:58] bit + // -- if 00, 11: guest + // -- if 01, 10: vmm extr.u r19 = r28, 58, 2 ;; cmp.eq p10, p0 = 0x0, r19 @@ -341,17 +358,16 @@ ENTRY(dtlb_miss) (p11) br.cond.sptk 2f // Is the faulted address is in the identity mapping area? - // 0xf000... or 0xe8000... + // must be either 0xf000... or 0xe8000... extr.u r20 = r16, 59, 5 ;; - cmp.eq p12, p0 = 0x1e, r20 // (0xf0 >> 3) = 0x1e + cmp.eq p12, p0 = 0x1e, r20 // (0xf0 >> 3) = 0x1e (p12) br.cond.spnt 1f - cmp.eq p0, p13 = 0x1d, r20 // (0xe8 >> 3) = 0x1d + cmp.eq p0, p13 = 0x1d, r20 // (0xe8 >> 3) = 0x1d (p13) br.cond.sptk 2f 1: - // xen identity mappin area. - movl r24=PAGE_KERNEL + movl r24=PAGE_KERNEL // xen identity mapping area. movl r25=(((1 << IA64_MAX_PHYS_BITS) - 1) & ~0xfff) ;; shr.u r26=r16,55 // move address bit 59 to bit 4 @@ -361,7 +377,8 @@ 1: ;; or r25=r25,r24 // insert PTE control bits into r25 ;; - or r25=r25,r26 // set bit 4 (uncached) if the access was to region 6 + or r25=r25,r26 // set bit 4 (uncached) if the access was to + // region 6 ;; itc.d r25 // insert the TLB entry mov pr=r31,-1 @@ -388,7 +405,8 @@ 2: #endif dtlb_fault: mov r17=cr.iha // get virtual address of L3 PTE - movl r30=1f // load nested fault continuation point + movl r30=1f // load nested fault + // continuation point ;; 1: ld8 r18=[r17] // read L3 PTE ;; @@ -400,13 +418,13 @@ 1: ld8 r18=[r17] // read L3 PTE ;; #ifdef CONFIG_SMP /* - * Tell the assemblers dependency-violation checker that the above "itc" instructions - * cannot possibly affect the following loads: + * Tell the assemblers dependency-violation checker that the above + * "itc" instructions cannot possibly affect the following loads: */ dv_serialize_data - ld8 r19=[r17] // read L3 PTE again and see if same - mov r20=PAGE_SHIFT<<2 // setup page size for purge + ld8 r19=[r17] // read L3 PTE again and see if same + mov r20=PAGE_SHIFT<<2 // setup page size for purge ;; cmp.ne p7,p0=r18,r19 ;; @@ -417,7 +435,7 @@ END(dtlb_miss) END(dtlb_miss) .org ia64_ivt+0x0c00 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x0c00 Entry 3 (size 64 bundles) Alt ITLB (19) ENTRY(alt_itlb_miss) DBG_FAULT(3) @@ -439,14 +457,14 @@ late_alt_itlb_miss: ;; #endif #ifdef CONFIG_DISABLE_VHPT - shr.u r22=r16,61 // get the region number into r21 - ;; - cmp.gt p8,p0=6,r22 // user mode + shr.u r22=r16,61 // get the region number into r21 + ;; + cmp.gt p8,p0=6,r22 // user mode ;; (p8) thash r17=r16 ;; (p8) mov cr.iha=r17 -(p8) mov r29=b0 // save b0 +(p8) mov r29=b0 // save b0 (p8) br.cond.dptk .itlb_fault #endif extr.u r23=r21,IA64_PSR_CPL0_BIT,2 // extract psr.cpl @@ -463,7 +481,8 @@ late_alt_itlb_miss: cmp.ne p8,p0=r0,r23 // psr.cpl != 0? or r19=r17,r19 // insert PTE control bits into r19 ;; - or r19=r19,r18 // set bit 4 (uncached) if the access was to region 6 + or r19=r19,r18 // set bit 4 (uncached) if the access was to + // region 6 (p8) br.cond.spnt page_fault ;; itc.i r19 // insert the TLB entry @@ -472,7 +491,7 @@ END(alt_itlb_miss) END(alt_itlb_miss) .org ia64_ivt+0x1000 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x1000 Entry 4 (size 64 bundles) Alt DTLB (7,46) ENTRY(alt_dtlb_miss) DBG_FAULT(4) @@ -503,13 +522,15 @@ late_alt_dtlb_miss: tbit.nz p6,p7=r20,IA64_ISR_SP_BIT // is speculation bit on? #ifdef XEN shr.u r18=r16,55 // move address bit 59 to bit 4 - and r19=r19,r16 // clear ed, reserved bits, and PTE control bits + and r19=r19,r16 // clear ed, reserved bits, and + // PTE control bits tbit.nz p9,p0=r20,IA64_ISR_NA_BIT // is non-access bit on? ;; and r18=0x10,r18 // bit 4=address-bit(59) #else shr.u r18=r16,57 // move address bit 61 to bit 4 - and r19=r19,r16 // clear ed, reserved bits, and PTE control bits + and r19=r19,r16 // clear ed, reserved bits, and + // PTE control bits tbit.nz p9,p0=r20,IA64_ISR_NA_BIT // is non-access bit on? ;; andcm r18=0x10,r18 // bit 4=~address-bit(61) @@ -520,36 +541,41 @@ late_alt_dtlb_miss: #ifdef XEN ;; #ifdef CONFIG_VIRTUAL_FRAME_TABLE - // Test for the address of virtual frame_table - shr r22=r16,56;; + shr r22=r16,56 // Test for the address of virtual frame_table + ;; cmp.eq p8,p0=((VIRT_FRAME_TABLE_ADDR>>56)&0xff)-0x100,r22 (p8) br.cond.sptk frametable_miss ;; #endif - // Test for Xen address, if not handle via page_fault - // note that 0xf000 (cached) and 0xe800 (uncached) addresses + // If it is not a Xen address, handle it via page_fault. + // Note that 0xf000 (cached) and 0xe800 (uncached) addresses // should be OK. - extr.u r22=r16,59,5;; + extr.u r22=r16,59,5 + ;; cmp.eq p8,p0=0x1e,r22 -(p8) br.cond.spnt 1f;; +(p8) br.cond.spnt 1f + ;; cmp.ne p8,p0=0x1d,r22 -(p8) br.cond.sptk page_fault ;; +(p8) br.cond.sptk page_fault + ;; 1: #endif dep r21=-1,r21,IA64_PSR_ED_BIT,1 or r19=r19,r17 // insert PTE control bits into r19 ;; - or r19=r19,r18 // set bit 4 (uncached) if the access was to region 6 + or r19=r19,r18 // set bit 4 (uncached) if the access was to + // region 6 (p6) mov cr.ipsr=r21 ;; (p7) itc.d r19 // insert the TLB entry mov pr=r31,-1 rfi END(alt_dtlb_miss) + #ifdef CONFIG_VIRTUAL_FRAME_TABLE GLOBAL_ENTRY(frametable_miss) rsm psr.dt // switch to using physical data addressing - movl r24=(frametable_pg_dir-PAGE_OFFSET) // r24=__pa(frametable_pg_dir) + movl r24=(frametable_pg_dir-PAGE_OFFSET) // r24=__pa(frametable_pg_dir) ;; srlz.d extr.u r17=r16,PGDIR_SHIFT,(PAGE_SHIFT-3) @@ -583,6 +609,7 @@ GLOBAL_ENTRY(frametable_miss) mov pr=r31,-1 // restore predicate registers rfi END(frametable_miss) + ENTRY(frametable_fault) ssm psr.dt // switch to using virtual data addressing mov r18=cr.iip @@ -590,7 +617,8 @@ ENTRY(frametable_fault) ;; cmp.eq p6,p7=r18,r19 // is faulting addrress ia64_frametable_probe? mov r8=0 // assumes that 'probe.r' uses r8 - dep r21=-1,r21,IA64_PSR_RI_BIT+1,1 // return to next instrucition in bundle 2 + dep r21=-1,r21,IA64_PSR_RI_BIT+1,1 // return to next instruction in + // bundle 2 ;; (p6) mov cr.ipsr=r21 mov r19=4 // FAULT(4) @@ -599,6 +627,7 @@ ENTRY(frametable_fault) mov pr=r31,-1 rfi END(frametable_fault) + GLOBAL_ENTRY(ia64_frametable_probe) { probe.r r8=r32,0 // destination register must be r8 @@ -615,18 +644,19 @@ ENTRY(nested_dtlb_miss) DBG_FAULT(5) #ifdef XEN mov b0=r30 - br.sptk.many b0 // return to continuation point - ;; -#else - /* - * In the absence of kernel bugs, we get here when the virtually mapped linear - * page table is accessed non-speculatively (e.g., in the Dirty-bit, Instruction - * Access-bit, or Data Access-bit faults). If the DTLB entry for the virtual page - * table is missing, a nested TLB miss fault is triggered and control is - * transferred to this point. When this happens, we lookup the pte for the - * faulting address by walking the page table in physical mode and return to the - * continuation point passed in register r30 (or call page_fault if the address is - * not mapped). + br.sptk.many b0 // return to the continuation point + ;; +#else + /* + * In the absence of kernel bugs, we get here when the virtually + * mapped linear page table is accessed non-speculatively (e.g., + * in the Dirty-bit, Instruction Access-bit, or Data Access-bit + * faults). If the DTLB entry for the virtual page table is missing, + * a nested TLB miss fault is triggered and control is transferred + * to this point. When this happens, we lookup the pte for the + * faulting address by walking the page table in physical mode + * and return to the continuation point passed in register r30 + * (or call page_fault if the address is not mapped). * * Input: r16: faulting address * r29: saved b0 @@ -640,47 +670,52 @@ ENTRY(nested_dtlb_miss) * * Clobbered: b0, r18, r19, r21, psr.dt (cleared) */ - rsm psr.dt // switch to using physical data addressing - mov r19=IA64_KR(PT_BASE) // get the page table base address - shl r21=r16,3 // shift bit 60 into sign bit - ;; - shr.u r17=r16,61 // get the region number into r17 - ;; - cmp.eq p6,p7=5,r17 // is faulting address in region 5? - shr.u r18=r16,PGDIR_SHIFT // get bits 33-63 of faulting address - ;; -(p7) dep r17=r17,r19,(PAGE_SHIFT-3),3 // put region number bits in place + rsm psr.dt // switch to using physical data + // addressing + mov r19=IA64_KR(PT_BASE) // get the page table base address + shl r21=r16,3 // shift bit 60 into sign bit + ;; + shr.u r17=r16,61 // get the region number into r17 + ;; + cmp.eq p6,p7=5,r17 // is faulting address in region 5? + shr.u r18=r16,PGDIR_SHIFT // get bits 33-63 of faulting address + ;; +(p7) dep r17=r17,r19,(PAGE_SHIFT-3),3 // put region number bits in place srlz.d - LOAD_PHYSICAL(p6, r19, swapper_pg_dir) // region 5 is rooted at swapper_pg_dir + LOAD_PHYSICAL(p6, r19, swapper_pg_dir) // region 5 is rooted at + // swapper_pg_dir .pred.rel "mutex", p6, p7 (p6) shr.u r21=r21,PGDIR_SHIFT+PAGE_SHIFT (p7) shr.u r21=r21,PGDIR_SHIFT+PAGE_SHIFT-3 ;; -(p6) dep r17=r18,r19,3,(PAGE_SHIFT-3) // r17=PTA + IFA(33,42)*8 -(p7) dep r17=r18,r17,3,(PAGE_SHIFT-6) // r17=PTA + (((IFA(61,63) << 7) | IFA(33,39))*8) - cmp.eq p7,p6=0,r21 // unused address bits all zeroes? - shr.u r18=r16,PMD_SHIFT // shift L2 index into position - ;; - ld8 r17=[r17] // fetch the L1 entry (may be 0) - ;; -(p7) cmp.eq p6,p7=r17,r0 // was L1 entry NULL? - dep r17=r18,r17,3,(PAGE_SHIFT-3) // compute address of L2 page table entry - ;; -(p7) ld8 r17=[r17] // fetch the L2 entry (may be 0) - shr.u r19=r16,PAGE_SHIFT // shift L3 index into position - ;; -(p7) cmp.eq.or.andcm p6,p7=r17,r0 // was L2 entry NULL? - dep r17=r19,r17,3,(PAGE_SHIFT-3) // compute address of L3 page table entry +(p6) dep r17=r18,r19,3,(PAGE_SHIFT-3) // r17=PTA + IFA(33,42)*8 +(p7) dep r17=r18,r17,3,(PAGE_SHIFT-6) // r17=PTA + (((IFA(61,63) << 7) | + // IFA(33,39))*8) + cmp.eq p7,p6=0,r21 // unused address bits all zeroes? + shr.u r18=r16,PMD_SHIFT // shift L2 index into position + ;; + ld8 r17=[r17] // fetch the L1 entry (may be 0) + ;; +(p7) cmp.eq p6,p7=r17,r0 // was L1 entry NULL? + dep r17=r18,r17,3,(PAGE_SHIFT-3) // compute address of L2 page table + // entry + ;; +(p7) ld8 r17=[r17] // fetch the L2 entry (may be 0) + shr.u r19=r16,PAGE_SHIFT // shift L3 index into position + ;; +(p7) cmp.eq.or.andcm p6,p7=r17,r0 // was L2 entry NULL? + dep r17=r19,r17,3,(PAGE_SHIFT-3) // compute address of L3 page table + // entry (p6) br.cond.spnt page_fault mov b0=r30 - br.sptk.many b0 // return to continuation point + br.sptk.many b0 // return to continuation point #endif END(nested_dtlb_miss) .org ia64_ivt+0x1800 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x1800 Entry 6 (size 64 bundles) Instruction Key Miss (24) ENTRY(ikey_miss) DBG_FAULT(6) @@ -691,8 +726,9 @@ ENTRY(ikey_miss) #endif END(ikey_miss) - //----------------------------------------------------------------------------------- - // call do_page_fault (predicates are in r31, psr.dt may be off, r16 is faulting address) + //---------------------------------------------------------------- + // call do_page_fault (predicates are in r31, psr.dt may be off, + // r16 is faulting address) #ifdef XEN GLOBAL_ENTRY(page_fault) #else @@ -713,24 +749,25 @@ ENTRY(page_fault) mov out0=cr.ifa mov out1=cr.isr #endif - adds r3=8,r2 // set up second base pointer + adds r3=8,r2 // set up second base pointer ;; ssm psr.ic | PSR_DEFAULT_BITS ;; - srlz.i // guarantee that interruption collectin is on - ;; -(p15) ssm psr.i // restore psr.i + srlz.i // guarantee that interruption + // collection is on + ;; +(p15) ssm psr.i // restore psr.i movl r14=ia64_leave_kernel ;; SAVE_REST mov rp=r14 ;; - adds out2=16,r12 // out2 = pointer to pt_regs + adds out2=16,r12 // out2 = pointer to pt_regs br.call.sptk.many b6=ia64_do_page_fault // ignore return address END(page_fault) .org ia64_ivt+0x1c00 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x1c00 Entry 7 (size 64 bundles) Data Key Miss (12,51) ENTRY(dkey_miss) DBG_FAULT(7) @@ -742,32 +779,33 @@ END(dkey_miss) END(dkey_miss) .org ia64_ivt+0x2000 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x2000 Entry 8 (size 64 bundles) Dirty-bit (54) ENTRY(dirty_bit) DBG_FAULT(8) #ifdef XEN mov r20=cr.ipsr - mov r31=pr;; - extr.u r20=r20,IA64_PSR_CPL0_BIT,2;; - mov r19=8 /* prepare to save predicates */ - cmp.eq p6,p0=r0,r20 /* cpl == 0?*/ + mov r31=pr + ;; + extr.u r20=r20,IA64_PSR_CPL0_BIT,2 + ;; + mov r19=8 // prepare to save predicates + cmp.eq p6,p0=r0,r20 // cpl == 0? (p6) br.sptk.few dispatch_to_fault_handler - /* If shadow mode is not enabled, reflect the fault. */ + // If shadow mode is not enabled, reflect the fault. movl r22=THIS_CPU(cpu_kr)+IA64_KR_CURRENT_OFFSET ;; ld8 r22=[r22] ;; add r22=IA64_VCPU_DOMAIN_OFFSET,r22 ;; - /* Read domain. */ + ld8 r22=[r22] // read domain + ;; + add r22=IA64_DOMAIN_SHADOW_BITMAP_OFFSET,r22 + ;; ld8 r22=[r22] ;; - add r22=IA64_DOMAIN_SHADOW_BITMAP_OFFSET,r22 - ;; - ld8 r22=[r22] - ;; - cmp.eq p6,p0=r0,r22 /* !shadow_bitmap ?*/ + cmp.eq p6,p0=r0,r22 // !shadow_bitmap ? (p6) br.dptk.many dispatch_reflection SAVE_MIN_WITH_COVER @@ -779,10 +817,11 @@ ENTRY(dirty_bit) ssm psr.ic | PSR_DEFAULT_BITS ;; - srlz.i // guarantee that interruption collection is on - ;; -(p15) ssm psr.i // restore psr.i - adds r3=8,r2 // set up second base pointer + srlz.i // guarantee that interruption + // collection is on + ;; +(p15) ssm psr.i // restore psr.i + adds r3=8,r2 // set up second base pointer ;; SAVE_REST movl r14=ia64_leave_kernel @@ -791,65 +830,69 @@ ENTRY(dirty_bit) br.call.sptk.many b6=ia64_shadow_fault #else /* - * What we do here is to simply turn on the dirty bit in the PTE. We need to - * update both the page-table and the TLB entry. To efficiently access the PTE, - * we address it through the virtual page table. Most likely, the TLB entry for - * the relevant virtual page table page is still present in the TLB so we can - * normally do this without additional TLB misses. In case the necessary virtual - * page table TLB entry isn't present, we take a nested TLB miss hit where we look - * up the physical address of the L3 PTE and then continue at label 1 below. - */ - mov r16=cr.ifa // get the address that caused the fault - movl r30=1f // load continuation point in case of nested fault - ;; - thash r17=r16 // compute virtual address of L3 PTE - mov r29=b0 // save b0 in case of nested fault - mov r31=pr // save pr + * What we do here is to simply turn on the dirty bit in the PTE. + * We need to update both the page-table and the TLB entry. To + * efficiently access the PTE, we address it through the virtual + * page table. Most likely, the TLB entry for the relevant virtual + * page table page is still present in the TLB so we can normally + * do this without additional TLB misses. In case the necessary + * virtual page table TLB entry isn't present, we take a nested + * TLB miss hit where we look up the physical address of the L3 + * PTE and then continue at label 1 below. + */ + mov r16=cr.ifa // get the address that caused the + // fault + movl r30=1f // load continuation point in case + // of nested fault + ;; + thash r17=r16 // compute virtual address of L3 PTE + mov r29=b0 // save b0 in case of nested fault + mov r31=pr // save pr #ifdef CONFIG_SMP - mov r28=ar.ccv // save ar.ccv + mov r28=ar.ccv // save ar.ccv ;; 1: ld8 r18=[r17] - ;; // avoid RAW on r18 - mov ar.ccv=r18 // set compare value for cmpxchg - or r25=_PAGE_D|_PAGE_A,r18 // set the dirty and accessed bits + ;; // avoid RAW on r18 + mov ar.ccv=r18 // set compare value for cmpxchg + or r25=_PAGE_D|_PAGE_A,r18 // set the dirty and accessed bits ;; cmpxchg8.acq r26=[r17],r25,ar.ccv mov r24=PAGE_SHIFT<<2 ;; cmp.eq p6,p7=r26,r18 ;; -(p6) itc.d r25 // install updated PTE - ;; - /* - * Tell the assemblers dependency-violation checker that the above "itc" instructions - * cannot possibly affect the following loads: +(p6) itc.d r25 // install updated PTE + ;; + /* + * Tell the assemblers dependency-violation checker that the above + * "itc" instructions cannot possibly affect the following loads: */ dv_serialize_data - ld8 r18=[r17] // read PTE again - ;; - cmp.eq p6,p7=r18,r25 // is it same as the newly installed + ld8 r18=[r17] // read PTE again + ;; + cmp.eq p6,p7=r18,r25 // is it same as the newly installed ;; (p7) ptc.l r16,r24 - mov b0=r29 // restore b0 + mov b0=r29 // restore b0 mov ar.ccv=r28 #else ;; 1: ld8 r18=[r17] - ;; // avoid RAW on r18 - or r18=_PAGE_D|_PAGE_A,r18 // set the dirty and accessed bits - mov b0=r29 // restore b0 - ;; - st8 [r17]=r18 // store back updated PTE - itc.d r18 // install updated PTE -#endif - mov pr=r31,-1 // restore pr + ;; // avoid RAW on r18 + or r18=_PAGE_D|_PAGE_A,r18 // set the dirty and accessed bits + mov b0=r29 // restore b0 + ;; + st8 [r17]=r18 // store back updated PTE + itc.d r18 // install updated PTE +#endif + mov pr=r31,-1 // restore pr rfi #endif END(dirty_bit) .org ia64_ivt+0x2400 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x2400 Entry 9 (size 64 bundles) Instruction Access-bit (27) ENTRY(iaccess_bit) DBG_FAULT(9) @@ -862,9 +905,11 @@ ENTRY(iaccess_bit) br.sptk.many fast_access_reflect;; #else // Like Entry 8, except for instruction access - mov r16=cr.ifa // get the address that caused the fault - movl r30=1f // load continuation point in case of nested fault - mov r31=pr // save predicates + mov r16=cr.ifa // get the address that caused the + // fault + movl r30=1f // load continuation point in case + // of nested fault + mov r31=pr // save predicates #ifdef CONFIG_ITANIUM /* * Erratum 10 (IFA may contain incorrect address) has "NoFix" status. @@ -872,50 +917,50 @@ ENTRY(iaccess_bit) mov r17=cr.ipsr ;; mov r18=cr.iip - tbit.z p6,p0=r17,IA64_PSR_IS_BIT // IA64 instruction set? - ;; -(p6) mov r16=r18 // if so, use cr.iip instead of cr.ifa + tbit.z p6,p0=r17,IA64_PSR_IS_BIT // IA64 instruction set? + ;; +(p6) mov r16=r18 // if so, use cr.iip instead of cr.ifa #endif /* CONFIG_ITANIUM */ ;; - thash r17=r16 // compute virtual address of L3 PTE - mov r29=b0 // save b0 in case of nested fault) + thash r17=r16 // compute virtual address of L3 PTE + mov r29=b0 // save b0 in case of nested fault) #ifdef CONFIG_SMP - mov r28=ar.ccv // save ar.ccv + mov r28=ar.ccv // save ar.ccv ;; 1: ld8 r18=[r17] ;; - mov ar.ccv=r18 // set compare value for cmpxchg - or r25=_PAGE_A,r18 // set the accessed bit + mov ar.ccv=r18 // set compare value for cmpxchg + or r25=_PAGE_A,r18 // set the accessed bit ;; cmpxchg8.acq r26=[r17],r25,ar.ccv mov r24=PAGE_SHIFT<<2 ;; cmp.eq p6,p7=r26,r18 ;; -(p6) itc.i r25 // install updated PTE - ;; - /* - * Tell the assemblers dependency-violation checker that the above "itc" instructions - * cannot possibly affect the following loads: +(p6) itc.i r25 // install updated PTE + ;; + /* + * Tell the assemblers dependency-violation checker that the above + * "itc" instructions cannot possibly affect the following loads: */ dv_serialize_data - ld8 r18=[r17] // read PTE again - ;; - cmp.eq p6,p7=r18,r25 // is it same as the newly installed + ld8 r18=[r17] // read PTE again + ;; + cmp.eq p6,p7=r18,r25 // is it same as the newly installed ;; (p7) ptc.l r16,r24 - mov b0=r29 // restore b0 + mov b0=r29 // restore b0 mov ar.ccv=r28 #else /* !CONFIG_SMP */ ;; 1: ld8 r18=[r17] ;; - or r18=_PAGE_A,r18 // set the accessed bit - mov b0=r29 // restore b0 - ;; - st8 [r17]=r18 // store back updated PTE - itc.i r18 // install updated PTE + or r18=_PAGE_A,r18 // set the accessed bit + mov b0=r29 // restore b0 + ;; + st8 [r17]=r18 // store back updated PTE + itc.i r18 // install updated PTE #endif /* !CONFIG_SMP */ mov pr=r31,-1 rfi @@ -923,7 +968,7 @@ END(iaccess_bit) END(iaccess_bit) .org ia64_ivt+0x2800 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x2800 Entry 10 (size 64 bundles) Data Access-bit (15,55) ENTRY(daccess_bit) DBG_FAULT(10) @@ -933,74 +978,80 @@ ENTRY(daccess_bit) mov r31=pr mov r19=10 mov r20=0x2800 - br.sptk.many fast_access_reflect;; + br.sptk.many fast_access_reflect + ;; #else // Like Entry 8, except for data access - mov r16=cr.ifa // get the address that caused the fault - movl r30=1f // load continuation point in case of nested fault - ;; - thash r17=r16 // compute virtual address of L3 PTE + mov r16=cr.ifa // get the address that caused the + // fault + movl r30=1f // load continuation point in case + // of nested fault + ;; + thash r17=r16 // compute virtual address of L3 PTE mov r31=pr - mov r29=b0 // save b0 in case of nested fault) + mov r29=b0 // save b0 in case of nested fault) #ifdef CONFIG_SMP - mov r28=ar.ccv // save ar.ccv + mov r28=ar.ccv // save ar.ccv ;; 1: ld8 r18=[r17] - ;; // avoid RAW on r18 - mov ar.ccv=r18 // set compare value for cmpxchg - or r25=_PAGE_A,r18 // set the dirty bit + ;; // avoid RAW on r18 + mov ar.ccv=r18 // set compare value for cmpxchg + or r25=_PAGE_A,r18 // set the dirty bit ;; cmpxchg8.acq r26=[r17],r25,ar.ccv mov r24=PAGE_SHIFT<<2 ;; cmp.eq p6,p7=r26,r18 ;; -(p6) itc.d r25 // install updated PTE - /* - * Tell the assemblers dependency-violation checker that the above "itc" instructions - * cannot possibly affect the following loads: +(p6) itc.d r25 // install updated PTE + /* + * Tell the assemblers dependency-violation checker that the above + * "itc" instructions cannot possibly affect the following loads: */ dv_serialize_data ;; - ld8 r18=[r17] // read PTE again - ;; - cmp.eq p6,p7=r18,r25 // is it same as the newly installed + ld8 r18=[r17] // read PTE again + ;; + cmp.eq p6,p7=r18,r25 // is it same as the newly installed ;; (p7) ptc.l r16,r24 mov ar.ccv=r28 #else ;; 1: ld8 r18=[r17] - ;; // avoid RAW on r18 - or r18=_PAGE_A,r18 // set the accessed bit - ;; - st8 [r17]=r18 // store back updated PTE - itc.d r18 // install updated PTE -#endif - mov b0=r29 // restore b0 + ;; // avoid RAW on r18 + or r18=_PAGE_A,r18 // set the accessed bit + ;; + st8 [r17]=r18 // store back updated PTE + itc.d r18 // install updated PTE +#endif + mov b0=r29 // restore b0 mov pr=r31,-1 rfi #endif END(daccess_bit) .org ia64_ivt+0x2c00 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x2c00 Entry 11 (size 64 bundles) Break instruction (33) ENTRY(break_fault) /* - * The streamlined system call entry/exit paths only save/restore the initial part - * of pt_regs. This implies that the callers of system-calls must adhere to the - * normal procedure calling conventions. + * The streamlined system call entry/exit paths only save/restore + * the initial part of pt_regs. This implies that the callers of + * system-calls must adhere to the normal procedure calling + * conventions. * * Registers to be saved & restored: * CR registers: cr.ipsr, cr.iip, cr.ifs - * AR registers: ar.unat, ar.pfs, ar.rsc, ar.rnat, ar.bspstore, ar.fpsr + * AR registers: ar.unat, ar.pfs, ar.rsc, ar.rnat, ar.bspstore, + * ar.fpsr * others: pr, b0, b6, loadrs, r1, r11, r12, r13, r15 * Registers to be restored only: * r8-r11: output value from the system call. * - * During system call exit, scratch registers (including r15) are modified/cleared - * to prevent leaking bits from kernel to user level. + * During system call exit, scratch registers (including r15) are + * modified/cleared to prevent leaking bits from kernel to user + * level. */ DBG_FAULT(11) #ifdef XEN @@ -1009,13 +1060,17 @@ ENTRY(break_fault) mov r31=pr ;; cmp.eq p7,p0=r17,r0 -(p7) br.spnt.few dispatch_break_fault ;; +(p7) br.spnt.few dispatch_break_fault + ;; #ifdef CRASH_DEBUG - // panic can occur before domain0 is created. - // in such case referencing XSI_PSR_IC causes nested_dtlb_miss - movl r18=CDB_BREAK_NUM ;; - cmp.eq p7,p0=r17,r18 ;; -(p7) br.spnt.few dispatch_break_fault ;; + // A panic can occur before domain0 is created. In such cases, + // referencing XSI_PSR_IC causes nested_dtlb_miss. + movl r18=CDB_BREAK_NUM + ;; + cmp.eq p7,p0=r17,r18 + ;; +(p7) br.spnt.few dispatch_break_fault + ;; #endif movl r18=THIS_CPU(current_psr_ic_addr) ;; @@ -1026,17 +1081,19 @@ ENTRY(break_fault) cmp.eq p7,p0=r0,r17 // is this a psuedo-cover? (p7) br.spnt.many dispatch_privop_fault ;; - // if vpsr.ic is off, we have a hyperprivop - // A hyperprivop is hand-coded assembly with psr.ic off - // which means no calls, no use of r1-r15 and no memory accesses - // except to pinned addresses! + // If vpsr.ic is off, we have a hyperprivop. A hyperprivop is + // hand-coded assembly with psr.ic off which means it can make + // no calls, cannot use r1-r15, and it can have no memory accesses + // unless they are to pinned addresses! cmp4.eq p7,p0=r0,r19 (p7) br.sptk.many fast_hyperprivop ;; - movl r22=THIS_CPU(cpu_kr)+IA64_KR_CURRENT_OFFSET;; + movl r22=THIS_CPU(cpu_kr)+IA64_KR_CURRENT_OFFSET + ;; ld8 r22 = [r22] ;; - adds r22=IA64_VCPU_BREAKIMM_OFFSET,r22;; + adds r22=IA64_VCPU_BREAKIMM_OFFSET,r22 + ;; ld4 r23=[r22];; cmp4.eq p6,p7=r23,r17 // Xen-reserved breakimm? (p6) br.spnt.many dispatch_break_fault @@ -1056,78 +1113,86 @@ ENTRY(break_fault) mov r26=ar.pfs mov r28=cr.iip #ifndef XEN - mov r31=pr // prepare to save predicates + mov r31=pr // prepare to save predicates #endif mov r20=r1 ;; adds r16=IA64_TASK_THREAD_ON_USTACK_OFFSET,r16 - cmp.eq p0,p7=r18,r17 // is this a system call? (p7 <- false, if so) + cmp.eq p0,p7=r18,r17 // is this a system call? + // (p7 <- false, if so) (p7) br.cond.spnt non_syscall ;; - ld1 r17=[r16] // load current->thread.on_ustack flag - st1 [r16]=r0 // clear current->thread.on_ustack flag - add r1=-IA64_TASK_THREAD_ON_USTACK_OFFSET,r16 // set r1 for MINSTATE_START_SAVE_MIN_VIRT + ld1 r17=[r16] // load current->thread.on_ustack flag + st1 [r16]=r0 // clear current->thread.on_ustack flag + add r1=-IA64_TASK_THREAD_ON_USTACK_OFFSET,r16 + // set r1 for + // MINSTATE_START_SAVE_MIN_VIRT ;; invala /* adjust return address so we skip over the break instruction: */ - extr.u r8=r29,41,2 // extract ei field from cr.ipsr - ;; - cmp.eq p6,p7=2,r8 // isr.ei==2? - mov r2=r1 // setup r2 for ia64_syscall_setup - ;; -(p6) mov r8=0 // clear ei to 0 -(p6) adds r28=16,r28 // switch cr.iip to next bundle cr.ipsr.ei wrapped -(p7) adds r8=1,r8 // increment ei to next slot - ;; - cmp.eq pKStk,pUStk=r0,r17 // are we in kernel mode already? - dep r29=r8,r29,41,2 // insert new ei into cr.ipsr + extr.u r8=r29,41,2 // extract ei field from cr.ipsr + ;; + cmp.eq p6,p7=2,r8 // isr.ei==2? + mov r2=r1 // setup r2 for ia64_syscall_setup + ;; +(p6) mov r8=0 // clear ei to 0 +(p6) adds r28=16,r28 // switch cr.iip to next bundle + // cr.ipsr.ei wrapped +(p7) adds r8=1,r8 // increment ei to next slot + ;; + cmp.eq pKStk,pUStk=r0,r17 // are we in kernel mode already? + dep r29=r8,r29,41,2 // insert new ei into cr.ipsr ;; // switch from user to kernel RBS: MINSTATE_START_SAVE_MIN_VIRT br.call.sptk.many b7=ia64_syscall_setup ;; - MINSTATE_END_SAVE_MIN_VIRT // switch to bank 1 + MINSTATE_END_SAVE_MIN_VIRT // switch to bank 1 ssm psr.ic | PSR_DEFAULT_BITS ;; - srlz.i // guarantee that interruption collection is on + srlz.i // guarantee that interruption + // collection is on mov r3=NR_syscalls - 1 ;; -(p15) ssm psr.i // restore psr.i +(p15) ssm psr.i // restore psr.i // p10==true means out registers are more than 8 or r15's Nat is true (p10) br.cond.spnt.many ia64_ret_from_syscall ;; movl r16=sys_call_table - adds r15=-1024,r15 // r15 contains the syscall number---subtract 1024 + adds r15=-1024,r15 // r15 contains the syscall number -- + // subtract 1024 from it movl r2=ia64_ret_from_syscall ;; - shladd r20=r15,3,r16 // r20 = sys_call_table + 8*(syscall-1024) - cmp.leu p6,p7=r15,r3 // (syscall > 0 && syscall < 1024 + NR_syscalls) ? - mov rp=r2 // set the real return addr - ;; -(p6) ld8 r20=[r20] // load address of syscall entry point + shladd r20=r15,3,r16 // r20 = sys_call_table + + // 8*(syscall-1024) + cmp.leu p6,p7=r15,r3 // (syscall > 0 && syscall < 1024 + + // NR_syscalls) ? + mov rp=r2 // set the real return addr + ;; +(p6) ld8 r20=[r20] // load address of syscall entry point (p7) movl r20=sys_ni_syscall add r2=TI_FLAGS+IA64_TASK_SIZE,r13 ;; - ld4 r2=[r2] // r2 = current_thread_info()->flags - ;; - and r2=_TIF_SYSCALL_TRACEAUDIT,r2 // mask trace or audit + ld4 r2=[r2] // r2 = current_thread_info()->flags + ;; + and r2=_TIF_SYSCALL_TRACEAUDIT,r2 // mask trace or audit ;; cmp.eq p8,p0=r2,r0 mov b6=r20 ;; -(p8) br.call.sptk.many b6=b6 // ignore this return addr +(p8) br.call.sptk.many b6=b6 // ignore this return addr br.cond.sptk ia64_trace_syscall // NOT REACHED #endif END(break_fault) .org ia64_ivt+0x3000 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x3000 Entry 12 (size 64 bundles) External Interrupt (4) ENTRY(interrupt) DBG_FAULT(12) @@ -1138,11 +1203,16 @@ ENTRY(interrupt) // FIXME: this is a hack... use cpuinfo.ksoftirqd because its // not used anywhere else and we need a place to stash ivr and // there's no registers available unused by SAVE_MIN/REST - movl r29=THIS_CPU(cpu_info)+IA64_CPUINFO_KSOFTIRQD_OFFSET;; - st8 [r29]=r30;; - movl r28=slow_interrupt;; - mov r29=rp;; - mov rp=r28;; + movl r29=THIS_CPU(cpu_info)+IA64_CPUINFO_KSOFTIRQD_OFFSET + ;; + st8 [r29]=r30 + ;; + movl r28=slow_interrupt + ;; + mov r29=rp + ;; + mov rp=r28 + ;; br.cond.sptk.many fast_tick_reflect ;; slow_interrupt: @@ -1175,16 +1245,16 @@ END(interrupt) END(interrupt) .org ia64_ivt+0x3400 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x3400 Entry 13 (size 64 bundles) Reserved DBG_FAULT(13) FAULT(13) #ifdef XEN - // There is no particular reason for this code to be here, other than that - // there happens to be space here that would go unused otherwise. If this - // fault ever gets "unreserved", simply moved the following code to a more - // suitable spot... + // There is no particular reason for this code to be here, other + // than that there happens to be space here that would go unused + // otherwise. If this fault ever gets "unreserved", simply move + // the following code to a more suitable spot... GLOBAL_ENTRY(dispatch_break_fault) SAVE_MIN_WITH_COVER @@ -1198,32 +1268,32 @@ dispatch_break_fault_post_save: ssm psr.ic | PSR_DEFAULT_BITS ;; - srlz.i // guarantee that interruption collection is on - ;; -(p15) ssm psr.i // restore psr.i - adds r3=8,r2 // set up second base pointer + srlz.i // guarantee that interruption collection is on + ;; +(p15) ssm psr.i // restore psr.i + adds r3=8,r2 // set up second base pointer ;; SAVE_REST movl r14=ia64_leave_kernel ;; mov rp=r14 -// br.sptk.many ia64_prepare_handle_break - br.call.sptk.many b6=ia64_handle_break +// br.sptk.many ia64_prepare_handle_break // TODO: why commented out? + br.call.sptk.many b6=ia64_handle_break END(dispatch_break_fault) #endif .org ia64_ivt+0x3800 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x3800 Entry 14 (size 64 bundles) Reserved DBG_FAULT(14) FAULT(14) #ifndef XEN /* - * There is no particular reason for this code to be here, other than that - * there happens to be space here that would go unused otherwise. If this - * fault ever gets "unreserved", simply moved the following code to a more - * suitable spot... + * There is no particular reason for this code to be here, other + * than that there happens to be space here that would go unused + * otherwise. If this fault ever gets "unreserved", simply move + * the following code to a more suitable spot... * * ia64_syscall_setup() is a separate subroutine so that it can * allocate stacked registers so it can safely demine any @@ -1271,11 +1341,11 @@ GLOBAL_ENTRY(ia64_syscall_setup) # error This code assumes that b6 is the first field in pt_regs. #endif #endif - st8 [r1]=r19 // save b6 - add r16=PT(CR_IPSR),r1 // initialize first base pointer - add r17=PT(R11),r1 // initialize second base pointer - ;; - alloc r19=ar.pfs,8,0,0,0 // ensure in0-in7 are writable + st8 [r1]=r19 // save b6 + add r16=PT(CR_IPSR),r1 // initialize first base pointer + add r17=PT(R11),r1 // initialize second base pointer + ;; + alloc r19=ar.pfs,8,0,0,0 // ensure in0-in7 are writable st8 [r16]=r29,PT(AR_PFS)-PT(CR_IPSR) // save cr.ipsr tnat.nz p8,p0=in0 @@ -1312,18 +1382,20 @@ GLOBAL_ENTRY(ia64_syscall_setup) tnat.nz p11,p0=in3 ;; (p10) mov in2=-1 - tnat.nz p12,p0=in4 // [I0] + tnat.nz p12,p0=in4 // [I0] (p11) mov in3=-1 ;; (pUStk) st8 [r16]=r24,PT(PR)-PT(AR_RNAT) // save ar.rnat (pUStk) st8 [r17]=r23,PT(B0)-PT(AR_BSPSTORE) // save ar.bspstore - shl r18=r18,16 // compute ar.rsc to be used for "loadrs" + shl r18=r18,16 // compute ar.rsc to be used + // for "loadrs" ;; st8 [r16]=r31,PT(LOADRS)-PT(PR) // save predicates st8 [r17]=r28,PT(R1)-PT(B0) // save b0 - tnat.nz p13,p0=in5 // [I0] - ;; - st8 [r16]=r18,PT(R12)-PT(LOADRS) // save ar.rsc value for "loadrs" + tnat.nz p13,p0=in5 // [I0] + ;; + st8 [r16]=r18,PT(R12)-PT(LOADRS) // save ar.rsc value for + // "loadrs" st8.spill [r17]=r20,PT(R13)-PT(R1) // save original r1 (p12) mov in4=-1 ;; @@ -1336,32 +1408,34 @@ GLOBAL_ENTRY(ia64_syscall_setup) tnat.nz p14,p0=in6 cmp.lt p10,p9=r11,r8 // frame size can't be more than local+8 ;; - stf8 [r16]=f1 // ensure pt_regs.r8 != 0 (see handle_syscall_error) + stf8 [r16]=f1 // ensure pt_regs.r8 != 0 + // (see handle_syscall_error) (p9) tnat.nz p10,p0=r15 - adds r12=-16,r1 // switch to kernel memory stack (with 16 bytes of scratch) - - st8.spill [r17]=r15 // save r15 + adds r12=-16,r1 // switch to kernel memory stack (with 16 + // bytes of scratch) + + st8.spill [r17]=r15 // save r15 tnat.nz p8,p0=in7 nop.i 0 - mov r13=r2 // establish `current' - movl r1=__gp // establish kernel global pointer + mov r13=r2 // establish `current' + movl r1=__gp // establish kernel global pointer ;; (p14) mov in6=-1 (p8) mov in7=-1 nop.i 0 - cmp.eq pSys,pNonSys=r0,r0 // set pSys=1, pNonSys=0 + cmp.eq pSys,pNonSys=r0,r0 // set pSys=1, pNonSys=0 movl r17=FPSR_DEFAULT ;; - mov.m ar.fpsr=r17 // set ar.fpsr to kernel default value + mov.m ar.fpsr=r17 // set ar.fpsr to kernel default value (p10) mov r8=-EINVAL br.ret.sptk.many b7 END(ia64_syscall_setup) #endif /* XEN */ .org ia64_ivt+0x3c00 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x3c00 Entry 15 (size 64 bundles) Reserved DBG_FAULT(15) FAULT(15) @@ -1370,11 +1444,12 @@ END(ia64_syscall_setup) /* * Squatting in this space ... * - * This special case dispatcher for illegal operation faults allows preserved - * registers to be modified through a callback function (asm only) that is handed - * back from the fault handler in r8. Up to three arguments can be passed to the - * callback function by returning an aggregate with the callback as its first - * element, followed by the arguments. + * This special case dispatcher for illegal operation faults + * allows preserved registers to be modified through a callback + * function (asm only) that is handed back from the fault handler + * in r8. Up to three arguments can be passed to the callback + * function by returning an aggregate with the callback as its + * first element, followed by the arguments. */ ENTRY(dispatch_illegal_op_fault) SAVE_MIN_WITH_COVER @@ -1408,21 +1483,22 @@ END(dispatch_illegal_op_fault) #endif .org ia64_ivt+0x4000 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x4000 Entry 16 (size 64 bundles) Reserved DBG_FAULT(16) FAULT(16) #ifdef XEN - // There is no particular reason for this code to be here, other than that - // there happens to be space here that would go unused otherwise. If this - // fault ever gets "unreserved", simply moved the following code to a more - // suitable spot... + // There is no particular reason for this code to be here, other + // than that there happens to be space here that would go unused + // otherwise. If this fault ever gets "unreserved", simply move + // the following code to a more suitable spot... ENTRY(dispatch_privop_fault) SAVE_MIN_WITH_COVER ;; - alloc r14=ar.pfs,0,0,4,0 // now it's safe (must be first in insn group!) + alloc r14=ar.pfs,0,0,4,0 // now it's safe (must be first in + // insn group!) mov out0=cr.ifa adds out1=16,sp mov out2=cr.isr // FIXME: pity to make this slow access twice @@ -1430,23 +1506,24 @@ ENTRY(dispatch_privop_fault) ssm psr.ic | PSR_DEFAULT_BITS ;; - srlz.i // guarantee that interruption collection is on - ;; -(p15) ssm psr.i // restore psr.i - adds r3=8,r2 // set up second base pointer + srlz.i // guarantee that interruption + // collection is on + ;; +(p15) ssm psr.i // restore psr.i + adds r3=8,r2 // set up second base pointer ;; SAVE_REST movl r14=ia64_leave_kernel ;; mov rp=r14 -// br.sptk.many ia64_prepare_handle_privop - br.call.sptk.many b6=ia64_handle_privop +// br.sptk.many ia64_prepare_handle_privop // TODO: why commented out? + br.call.sptk.many b6=ia64_handle_privop END(dispatch_privop_fault) #endif .org ia64_ivt+0x4400 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x4400 Entry 17 (size 64 bundles) Reserved DBG_FAULT(17) FAULT(17) @@ -1455,77 +1532,80 @@ ENTRY(non_syscall) ENTRY(non_syscall) SAVE_MIN_WITH_COVER - // There is no particular reason for this code to be here, other than that - // there happens to be space here that would go unused otherwise. If this - // fault ever gets "unreserved", simply moved the following code to a more - // suitable spot... + // There is no particular reason for this code to be here, other + // than that there happens to be space here that would go unused + // otherwise. If this fault ever gets "unreserved", simply move + // the following code to a more suitable spot... alloc r14=ar.pfs,0,0,2,0 mov out0=cr.iim add out1=16,sp - adds r3=8,r2 // set up second base pointer for SAVE_REST + adds r3=8,r2 // set up second base pointer for SAVE_REST ssm psr.ic | PSR_DEFAULT_BITS ;; - srlz.i // guarantee that interruption collection is on - ;; -(p15) ssm psr.i // restore psr.i + srlz.i // guarantee that interruption collection is on + ;; +(p15) ssm psr.i // restore psr.i movl r15=ia64_leave_kernel ;; SAVE_REST mov rp=r15 ;; - br.call.sptk.many b6=ia64_bad_break // avoid WAW on CFM and ignore return addr + br.call.sptk.many b6=ia64_bad_break // avoid WAW on CFM and + // ignore return addr END(non_syscall) #endif .org ia64_ivt+0x4800 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x4800 Entry 18 (size 64 bundles) Reserved DBG_FAULT(18) FAULT(18) #ifndef XEN /* - * There is no particular reason for this code to be here, other than that - * there happens to be space here that would go unused otherwise. If this - * fault ever gets "unreserved", simply moved the following code to a more - * suitable spot... + * There is no particular reason for this code to be here, other + * than that there happens to be space here that would go unused + * otherwise. If this fault ever gets "unreserved", simply move + * the following code to a more suitable spot... */ ENTRY(dispatch_unaligned_handler) SAVE_MIN_WITH_COVER ;; - alloc r14=ar.pfs,0,0,2,0 // now it's safe (must be first in insn group!) + alloc r14=ar.pfs,0,0,2,0 // now it's safe (must be first in + // insn group!) mov out0=cr.ifa adds out1=16,sp ssm psr.ic | PSR_DEFAULT_BITS ;; - srlz.i // guarantee that interruption collection is on - ;; -(p15) ssm psr.i // restore psr.i - adds r3=8,r2 // set up second base pointer + srlz.i // guarantee that interruption + // collection is on + ;; +(p15) ssm psr.i // restore psr.i + adds r3=8,r2 // set up second base pointer ;; SAVE_REST movl r14=ia64_leave_kernel ;; mov rp=r14 -// br.sptk.many ia64_prepare_handle_unaligned - br.call.sptk.many b6=ia64_handle_unaligned +// br.sptk.many ia64_prepare_handle_unaligned // TODO: why commented out? + br.call.sptk.many b6=ia64_handle_unaligned END(dispatch_unaligned_handler) #endif .org ia64_ivt+0x4c00 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x4c00 Entry 19 (size 64 bundles) Reserved DBG_FAULT(19) FAULT(19) /* - * There is no particular reason for this code to be here, other than that - * there happens to be space here that would go unused otherwise. If this - * fault ever gets "unreserved", simply moved the following code to a more - * suitable spot... + * There is no particular reason for this code to be here, other + * than that there happens to be space here that would go unused + * otherwise. If this fault ever gets "unreserved", simply move + * the following code to a more suitable spot... */ GLOBAL_ENTRY(dispatch_to_fault_handler) @@ -1545,10 +1625,12 @@ GLOBAL_ENTRY(dispatch_to_fault_handler) ;; ssm psr.ic | PSR_DEFAULT_BITS ;; - srlz.i // guarantee that interruption collection is on - ;; -(p15) ssm psr.i // restore psr.i - adds r3=8,r2 // set up second base pointer for SAVE_REST + srlz.i // guarantee that interruption + // collection is on + ;; +(p15) ssm psr.i // restore psr.i + adds r3=8,r2 // set up second base pointer for + // SAVE_REST ;; SAVE_REST movl r14=ia64_leave_kernel @@ -1562,7 +1644,7 @@ END(dispatch_to_fault_handler) // .org ia64_ivt+0x5000 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x5000 Entry 20 (size 16 bundles) Page Not Present (10,22,49) ENTRY(page_not_present) DBG_FAULT(20) @@ -1572,8 +1654,9 @@ ENTRY(page_not_present) mov r16=cr.ifa rsm psr.dt /* - * The Linux page fault handler doesn't expect non-present pages to be in - * the TLB. Flush the existing entry now, so we meet that expectation. + * The Linux page fault handler doesn't expect non-present pages + * to be in the TLB. Flush the existing entry now, so we meet + * that expectation. */ mov r17=PAGE_SHIFT<<2 ;; @@ -1586,7 +1669,7 @@ END(page_not_present) END(page_not_present) .org ia64_ivt+0x5100 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x5100 Entry 21 (size 16 bundles) Key Permission (13,25,52) ENTRY(key_permission) DBG_FAULT(21) @@ -1603,7 +1686,7 @@ END(key_permission) END(key_permission) .org ia64_ivt+0x5200 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x5200 Entry 22 (size 16 bundles) Instruction Access Rights (26) ENTRY(iaccess_rights) DBG_FAULT(22) @@ -1620,17 +1703,19 @@ END(iaccess_rights) END(iaccess_rights) .org ia64_ivt+0x5300 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x5300 Entry 23 (size 16 bundles) Data Access Rights (14,53) ENTRY(daccess_rights) DBG_FAULT(23) #ifdef XEN - mov r31=pr; + mov r31=pr + ;; mov r16=cr.isr mov r17=cr.ifa mov r19=23 movl r20=0x5300 - br.sptk.many fast_access_reflect;; + br.sptk.many fast_access_reflect + ;; #else mov r16=cr.ifa rsm psr.dt @@ -1642,7 +1727,7 @@ END(daccess_rights) END(daccess_rights) .org ia64_ivt+0x5400 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x5400 Entry 24 (size 16 bundles) General Exception (5,32,34,36,38,39) ENTRY(general_exception) DBG_FAULT(24) @@ -1662,12 +1747,12 @@ END(general_exception) END(general_exception) .org ia64_ivt+0x5500 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x5500 Entry 25 (size 16 bundles) Disabled FP-Register (35) ENTRY(disabled_fp_reg) DBG_FAULT(25) #ifdef XEN -#if 0 +#if 0 // TODO: can this be removed? mov r20=pr movl r16=0x2000000000000000 movl r17=0x2000000000176b60 @@ -1686,7 +1771,7 @@ ENTRY(disabled_fp_reg) ;; #endif FAULT_OR_REFLECT(25) -//floating_panic: +//floating_panic: // TODO: can this be removed? // br.sptk.many floating_panic ;; #endif @@ -1699,7 +1784,7 @@ END(disabled_fp_reg) END(disabled_fp_reg) .org ia64_ivt+0x5600 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x5600 Entry 26 (size 16 bundles) Nat Consumption (11,23,37,50) ENTRY(nat_consumption) DBG_FAULT(26) @@ -1711,7 +1796,7 @@ END(nat_consumption) END(nat_consumption) .org ia64_ivt+0x5700 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x5700 Entry 27 (size 16 bundles) Speculation (40) ENTRY(speculation_vector) DBG_FAULT(27) @@ -1720,12 +1805,13 @@ ENTRY(speculation_vector) FAULT_OR_REFLECT(27) #else /* - * A [f]chk.[as] instruction needs to take the branch to the recovery code but - * this part of the architecture is not implemented in hardware on some CPUs, such - * as Itanium. Thus, in general we need to emulate the behavior. IIM contains - * the relative target (not yet sign extended). So after sign extending it we - * simply add it to IIP. We also need to reset the EI field of the IPSR to zero, - * i.e., the slot to restart into. + * A [f]chk.[as] instruction needs to take the branch to the + * recovery code but this part of the architecture is not + * implemented in hardware on some CPUs, such as Itanium. Thus, + * in general we need to emulate the behavior. IIM contains the + * relative target (not yet sign extended). So after sign extending + * it we simply add it to IIP. We also need to reset the EI field + * of the IPSR to zero, i.e., the slot to restart into. * * cr.imm contains zero_ext(imm21) */ @@ -1753,13 +1839,13 @@ END(speculation_vector) END(speculation_vector) .org ia64_ivt+0x5800 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x5800 Entry 28 (size 16 bundles) Reserved DBG_FAULT(28) FAULT(28) .org ia64_ivt+0x5900 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x5900 Entry 29 (size 16 bundles) Debug (16,28,56) ENTRY(debug_vector) DBG_FAULT(29) @@ -1771,7 +1857,7 @@ END(debug_vector) END(debug_vector) .org ia64_ivt+0x5a00 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x5a00 Entry 30 (size 16 bundles) Unaligned Reference (57) ENTRY(unaligned_access) DBG_FAULT(30) @@ -1786,7 +1872,7 @@ END(unaligned_access) END(unaligned_access) .org ia64_ivt+0x5b00 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x5b00 Entry 31 (size 16 bundles) Unsupported Data Reference (57) ENTRY(unsupported_data_reference) DBG_FAULT(31) @@ -1798,7 +1884,7 @@ END(unsupported_data_reference) END(unsupported_data_reference) .org ia64_ivt+0x5c00 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x5c00 Entry 32 (size 16 bundles) Floating-Point Fault (64) ENTRY(floating_point_fault) DBG_FAULT(32) @@ -1810,7 +1896,7 @@ END(floating_point_fault) END(floating_point_fault) .org ia64_ivt+0x5d00 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x5d00 Entry 33 (size 16 bundles) Floating Point Trap (66) ENTRY(floating_point_trap) DBG_FAULT(33) @@ -1822,7 +1908,7 @@ END(floating_point_trap) END(floating_point_trap) .org ia64_ivt+0x5e00 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x5e00 Entry 34 (size 16 bundles) Lower Privilege Transfer Trap (66) ENTRY(lower_privilege_trap) DBG_FAULT(34) @@ -1834,7 +1920,7 @@ END(lower_privilege_trap) END(lower_privilege_trap) .org ia64_ivt+0x5f00 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x5f00 Entry 35 (size 16 bundles) Taken Branch Trap (68) ENTRY(taken_branch_trap) DBG_FAULT(35) @@ -1846,7 +1932,7 @@ END(taken_branch_trap) END(taken_branch_trap) .org ia64_ivt+0x6000 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x6000 Entry 36 (size 16 bundles) Single Step Trap (69) ENTRY(single_step_trap) DBG_FAULT(36) @@ -1858,56 +1944,58 @@ END(single_step_trap) END(single_step_trap) .org ia64_ivt+0x6100 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x6100 Entry 37 (size 16 bundles) Reserved DBG_FAULT(37) FAULT(37) .org ia64_ivt+0x6200 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x6200 Entry 38 (size 16 bundles) Reserved DBG_FAULT(38) FAULT(38) .org ia64_ivt+0x6300 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x6300 Entry 39 (size 16 bundles) Reserved DBG_FAULT(39) FAULT(39) .org ia64_ivt+0x6400 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x6400 Entry 40 (size 16 bundles) Reserved DBG_FAULT(40) FAULT(40) .org ia64_ivt+0x6500 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x6500 Entry 41 (size 16 bundles) Reserved DBG_FAULT(41) FAULT(41) .org ia64_ivt+0x6600 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x6600 Entry 42 (size 16 bundles) Reserved DBG_FAULT(42) FAULT(42) .org ia64_ivt+0x6700 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x6700 Entry 43 (size 16 bundles) Reserved DBG_FAULT(43) FAULT(43) .org ia64_ivt+0x6800 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x6800 Entry 44 (size 16 bundles) Reserved DBG_FAULT(44) FAULT(44) .org ia64_ivt+0x6900 -///////////////////////////////////////////////////////////////////////////////////////// -// 0x6900 Entry 45 (size 16 bundles) IA-32 Exeception (17,18,29,41,42,43,44,58,60,61,62,72,73,75,76,77) +////////////////////////////////////////////////////////////////////////// +// 0x6900 Entry 45 (size 16 bundles) IA-32 Exeception (17,18,29,41,42,43, +// 44,58,60,61,62,72, +// 73,75,76,77) ENTRY(ia32_exception) DBG_FAULT(45) #ifdef XEN @@ -1918,7 +2006,7 @@ END(ia32_exception) END(ia32_exception) .org ia64_ivt+0x6a00 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x6a00 Entry 46 (size 16 bundles) IA-32 Intercept (30,31,59,70,71) ENTRY(ia32_intercept) DBG_FAULT(46) @@ -1952,7 +2040,7 @@ END(ia32_intercept) END(ia32_intercept) .org ia64_ivt+0x6b00 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x6b00 Entry 47 (size 16 bundles) IA-32 Interrupt (74) ENTRY(ia32_interrupt) DBG_FAULT(47) @@ -1969,121 +2057,121 @@ END(ia32_interrupt) END(ia32_interrupt) .org ia64_ivt+0x6c00 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x6c00 Entry 48 (size 16 bundles) Reserved DBG_FAULT(48) FAULT(48) .org ia64_ivt+0x6d00 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x6d00 Entry 49 (size 16 bundles) Reserved DBG_FAULT(49) FAULT(49) .org ia64_ivt+0x6e00 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x6e00 Entry 50 (size 16 bundles) Reserved DBG_FAULT(50) FAULT(50) .org ia64_ivt+0x6f00 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x6f00 Entry 51 (size 16 bundles) Reserved DBG_FAULT(51) FAULT(51) .org ia64_ivt+0x7000 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x7000 Entry 52 (size 16 bundles) Reserved DBG_FAULT(52) FAULT(52) .org ia64_ivt+0x7100 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x7100 Entry 53 (size 16 bundles) Reserved DBG_FAULT(53) FAULT(53) .org ia64_ivt+0x7200 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x7200 Entry 54 (size 16 bundles) Reserved DBG_FAULT(54) FAULT(54) .org ia64_ivt+0x7300 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x7300 Entry 55 (size 16 bundles) Reserved DBG_FAULT(55) FAULT(55) .org ia64_ivt+0x7400 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x7400 Entry 56 (size 16 bundles) Reserved DBG_FAULT(56) FAULT(56) .org ia64_ivt+0x7500 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x7500 Entry 57 (size 16 bundles) Reserved DBG_FAULT(57) FAULT(57) .org ia64_ivt+0x7600 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x7600 Entry 58 (size 16 bundles) Reserved DBG_FAULT(58) FAULT(58) .org ia64_ivt+0x7700 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x7700 Entry 59 (size 16 bundles) Reserved DBG_FAULT(59) FAULT(59) .org ia64_ivt+0x7800 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x7800 Entry 60 (size 16 bundles) Reserved DBG_FAULT(60) FAULT(60) .org ia64_ivt+0x7900 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x7900 Entry 61 (size 16 bundles) Reserved DBG_FAULT(61) FAULT(61) .org ia64_ivt+0x7a00 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x7a00 Entry 62 (size 16 bundles) Reserved DBG_FAULT(62) FAULT(62) .org ia64_ivt+0x7b00 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x7b00 Entry 63 (size 16 bundles) Reserved DBG_FAULT(63) FAULT(63) .org ia64_ivt+0x7c00 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x7c00 Entry 64 (size 16 bundles) Reserved DBG_FAULT(64) FAULT(64) .org ia64_ivt+0x7d00 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x7d00 Entry 65 (size 16 bundles) Reserved DBG_FAULT(65) FAULT(65) .org ia64_ivt+0x7e00 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x7e00 Entry 66 (size 16 bundles) Reserved DBG_FAULT(66) FAULT(66) .org ia64_ivt+0x7f00 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x7f00 Entry 67 (size 16 bundles) Reserved DBG_FAULT(67) FAULT(67) @@ -2104,21 +2192,22 @@ GLOBAL_ENTRY(dispatch_reflection) adds out1=16,sp mov out2=cr.isr mov out3=cr.iim -// mov out3=cr.itir +// mov out3=cr.itir // TODO: why commented out? ssm psr.ic | PSR_DEFAULT_BITS ;; - srlz.i // guarantee that interruption collection is on - ;; -(p15) ssm psr.i // restore psr.i - adds r3=8,r2 // set up second base pointer + srlz.i // guarantee that interruption + // collection is on + ;; +(p15) ssm psr.i // restore psr.i + adds r3=8,r2 // set up second base pointer ;; SAVE_REST movl r14=ia64_leave_kernel ;; mov rp=r14 -// br.sptk.many ia64_prepare_handle_reflection - br.call.sptk.many b6=ia64_handle_reflection +// br.sptk.many ia64_prepare_handle_reflection // TODO: why commented out? + br.call.sptk.many b6=ia64_handle_reflection END(dispatch_reflection) #define SAVE_MIN_COVER_DONE DO_SAVE_MIN(,mov r30=cr.ifs,) @@ -2134,10 +2223,10 @@ END(dispatch_slow_hyperprivop) #ifdef CONFIG_IA32_SUPPORT /* - * There is no particular reason for this code to be here, other than that - * there happens to be space here that would go unused otherwise. If this - * fault ever gets "unreserved", simply moved the following code to a more - * suitable spot... + * There is no particular reason for this code to be here, other + * than that there happens to be space here that would go unused + * otherwise. If this fault ever gets "unreserved", simply move + * the following code to a more suitable spot... */ // IA32 interrupt entry point @@ -2148,7 +2237,7 @@ ENTRY(dispatch_to_ia32_handler) mov r14=cr.isr ssm psr.ic | PSR_DEFAULT_BITS ;; - srlz.i // guarantee that interruption collection is on + srlz.i // guarantee that interruption collection is on ;; (p15) ssm psr.i adds r3=8,r2 // Base pointer for SAVE_REST @@ -2161,15 +2250,17 @@ ENTRY(dispatch_to_ia32_handler) cmp.ne p6,p0=r14,r15 (p6) br.call.dpnt.many b6=non_ia32_syscall - adds r14=IA64_PT_REGS_R8_OFFSET + 16,sp // 16 byte hole per SW conventions + adds r14=IA64_PT_REGS_R8_OFFSET + 16,sp // 16 byte hole per SW + // conventions adds r15=IA64_PT_REGS_R1_OFFSET + 16,sp ;; cmp.eq pSys,pNonSys=r0,r0 // set pSys=1, pNonSys=0 ld8 r8=[r14] // get r8 ;; - st8 [r15]=r8 // save original EAX in r1 (IA32 procs don't use the GP) - ;; - alloc r15=ar.pfs,0,0,6,0 // must first in an insn group + st8 [r15]=r8 // save original EAX in r1 (IA32 procs + // don't use the GP) + ;; + alloc r15=ar.pfs,0,0,6,0 // must be first in an insn group ;; ld4 r8=[r14],8 // r8 == eax (syscall number) mov r15=IA32_NR_syscalls @@ -2208,7 +2299,7 @@ non_ia32_syscall: alloc r15=ar.pfs,0,0,2,0 mov out0=r14 // interrupt # add out1=16,sp // pointer to pt_regs - ;; // avoid WAW on CFM + ;; // avoid WAW on CFM br.call.sptk.many rp=ia32_bad_interrupt .ret1: movl r15=ia64_leave_kernel ;; diff -r e01441c9a607 -r 50aea0ec406b xen/arch/ia64/xen/mm.c --- a/xen/arch/ia64/xen/mm.c Wed Aug 30 14:09:31 2006 -0500 +++ b/xen/arch/ia64/xen/mm.c Wed Aug 30 22:36:18 2006 +0100 @@ -166,7 +166,8 @@ #include <xen/sched.h> #include <xen/domain.h> #include <asm/xentypes.h> -#include <asm/mm.h> +#include <xen/mm.h> +#include <xen/errno.h> #include <asm/pgalloc.h> #include <asm/vhpt.h> #include <asm/vcpu.h> @@ -948,8 +949,6 @@ efi_mmio(unsigned long physaddr, unsigne return 1; } - DPRINTK("%s:%d physaddr 0x%lx size = 0x%lx\n", - __func__, __LINE__, physaddr, size); return 0; } @@ -970,8 +969,10 @@ assign_domain_mmio_page(struct domain *d __func__, d, mpaddr, size); } if (!efi_mmio(mpaddr, size)) { +#ifndef NDEBUG DPRINTK("%s:%d domain %p mpaddr 0x%lx size = 0x%lx\n", __func__, __LINE__, d, mpaddr, size); +#endif return -EINVAL; } assign_domain_same_page(d, mpaddr, size, ASSIGN_writable | ASSIGN_nocache); diff -r e01441c9a607 -r 50aea0ec406b xen/arch/ia64/xen/pcdp.c --- a/xen/arch/ia64/xen/pcdp.c Wed Aug 30 14:09:31 2006 -0500 +++ b/xen/arch/ia64/xen/pcdp.c Wed Aug 30 22:36:18 2006 +0100 @@ -18,6 +18,7 @@ #ifdef XEN #include <linux/efi.h> #include <linux/errno.h> +#include <asm/io.h> #include <asm/iosapic.h> #include <asm/system.h> #include <acpi/acpi.h> diff -r e01441c9a607 -r 50aea0ec406b xen/arch/ia64/xen/privop.c --- a/xen/arch/ia64/xen/privop.c Wed Aug 30 14:09:31 2006 -0500 +++ b/xen/arch/ia64/xen/privop.c Wed Aug 30 22:36:18 2006 +0100 @@ -13,7 +13,7 @@ #include <asm/dom_fw.h> #include <asm/vhpt.h> #include <asm/bundle.h> -#include <asm/privop_stat.h> +#include <xen/perfc.h> long priv_verbose=0; unsigned long privop_trace = 0; @@ -682,7 +682,7 @@ priv_emulate(VCPU *vcpu, REGS *regs, UIN return IA64_ILLOP_FAULT; } //if (isrcode != 1 && isrcode != 2) return 0; - privlvl = (ipsr & IA64_PSR_CPL) >> IA64_PSR_CPL0_BIT; + privlvl = ia64_get_cpl(ipsr); // its OK for a privified-cover to be executed in user-land fault = priv_handle_op(vcpu,regs,privlvl); if ((fault == IA64_NO_FAULT) || (fault == IA64_EXTINT_VECTOR)) { // success!! diff -r e01441c9a607 -r 50aea0ec406b xen/arch/ia64/xen/privop_stat.c --- a/xen/arch/ia64/xen/privop_stat.c Wed Aug 30 14:09:31 2006 -0500 +++ b/xen/arch/ia64/xen/privop_stat.c Wed Aug 30 22:36:18 2006 +0100 @@ -1,26 +1,55 @@ +#include <xen/lib.h> +#include <public/xen.h> +#include <xen/perfc.h> +#include <asm/atomic.h> #include <asm/privop_stat.h> -#include <asm/vhpt.h> -#include <xen/lib.h> -#include <asm/uaccess.h> -#ifdef PRIVOP_ADDR_COUNT -#define PRIVOP_COUNT_NINSTS 2 -#define PRIVOP_COUNT_NADDRS 30 +#ifdef CONFIG_PRIVOP_ADDRS struct privop_addr_count { - const char *instname; unsigned long addr[PRIVOP_COUNT_NADDRS]; - unsigned long count[PRIVOP_COUNT_NADDRS]; - unsigned long overflow; + unsigned int count[PRIVOP_COUNT_NADDRS]; + unsigned int overflow; + atomic_t *perfc_addr; + atomic_t *perfc_count; + atomic_t *perfc_overflow; }; +#undef PERFCOUNTER +#define PERFCOUNTER(var, name) -static struct privop_addr_count privop_addr_counter[PRIVOP_COUNT_NINSTS] = { - [_GET_IFA] = { "=ifa", { 0 }, { 0 }, 0 }, - [_THASH] = { "thash", { 0 }, { 0 }, 0 } +#undef PERFCOUNTER_CPU +#define PERFCOUNTER_CPU(var, name) + +#undef PERFCOUNTER_ARRAY +#define PERFCOUNTER_ARRAY(var, name, size) + +#undef PERFSTATUS +#define PERFSTATUS(var, name) + +#undef PERFSTATUS_CPU +#define PERFSTATUS_CPU(var, name) + +#undef PERFSTATUS_ARRAY +#define PERFSTATUS_ARRAY(var, name, size) + +#undef PERFPRIVOPADDR +#define PERFPRIVOPADDR(name) \ + { \ + { 0 }, { 0 }, 0, \ + perfcounters.privop_addr_##name##_addr, \ + perfcounters.privop_addr_##name##_count, \ + perfcounters.privop_addr_##name##_overflow \ + }, + +static struct privop_addr_count privop_addr_counter[] = { +#include <asm/perfc_defn.h> }; -void privop_count_addr(unsigned long iip, int inst) +#define PRIVOP_COUNT_NINSTS \ + (sizeof(privop_addr_counter) / sizeof(privop_addr_counter[0])) + +void privop_count_addr(unsigned long iip, enum privop_inst inst) { struct privop_addr_count *v = &privop_addr_counter[inst]; int i; @@ -41,29 +70,28 @@ void privop_count_addr(unsigned long iip v->overflow++;; } -static int dump_privop_addrs(char *buf) +void gather_privop_addrs(void) { int i, j; - char *s = buf; - s += sprintf(s, "Privop addresses:\n"); + atomic_t *v; for (i = 0; i < PRIVOP_COUNT_NINSTS; i++) { - struct privop_addr_count *v = &privop_addr_counter[i]; - s += sprintf(s, "%s:\n", v->instname); - for (j = 0; j < PRIVOP_COUNT_NADDRS; j++) { - if (!v->addr[j]) - break; - s += sprintf(s, " at 0x%lx #%ld\n", - v->addr[j], v->count[j]); - } - if (v->overflow) - s += sprintf(s, " other #%ld\n", v->overflow); + /* Note: addresses are truncated! */ + v = privop_addr_counter[i].perfc_addr; + for (j = 0; j < PRIVOP_COUNT_NADDRS; j++) + atomic_set(&v[j], privop_addr_counter[i].addr[j]); + + v = privop_addr_counter[i].perfc_count; + for (j = 0; j < PRIVOP_COUNT_NADDRS; j++) + atomic_set(&v[j], privop_addr_counter[i].count[j]); + + atomic_set(privop_addr_counter[i].perfc_overflow, + privop_addr_counter[i].overflow); } - return s - buf; } -static void zero_privop_addrs(void) +void reset_privop_addrs(void) { - int i,j; + int i, j; for (i = 0; i < PRIVOP_COUNT_NINSTS; i++) { struct privop_addr_count *v = &privop_addr_counter[i]; for (j = 0; j < PRIVOP_COUNT_NADDRS; j++) @@ -119,30 +147,3 @@ static const char * const hyperpriv_str[ "=rr", "rr=", "kr=", "fc", "=cpuid", "=pmd", "=ar.eflg", "ar.eflg=" }; #endif - -#define TMPBUFLEN 8*1024 -int dump_privop_counts_to_user(char __user *ubuf, int len) -{ - char buf[TMPBUFLEN]; - int n; - - if (len < TMPBUFLEN) - return -1; - - n = 0; -#ifdef PRIVOP_ADDR_COUNT - n += dump_privop_addrs(buf + n); -#endif - n += dump_vhpt_stats(buf + n); - if (__copy_to_user(ubuf,buf,n)) - return -1; - return n; -} - -int zero_privop_counts_to_user(char __user *ubuf, int len) -{ -#ifdef PRIVOP_ADDR_COUNT - zero_privop_addrs(); -#endif - return 0; -} diff -r e01441c9a607 -r 50aea0ec406b xen/arch/ia64/xen/vcpu.c --- a/xen/arch/ia64/xen/vcpu.c Wed Aug 30 14:09:31 2006 -0500 +++ b/xen/arch/ia64/xen/vcpu.c Wed Aug 30 22:36:18 2006 +0100 @@ -8,6 +8,7 @@ #include <linux/sched.h> #include <public/xen.h> +#include <xen/mm.h> #include <asm/ia64_int.h> #include <asm/vcpu.h> #include <asm/regionreg.h> @@ -22,6 +23,7 @@ #include <asm/vmx_phy_mode.h> #include <asm/bundle.h> #include <asm/privop_stat.h> +#include <asm/uaccess.h> /* FIXME: where these declarations should be there ? */ extern void getreg(unsigned long regnum, unsigned long *val, int *nat, struct pt_regs *regs); @@ -473,7 +475,7 @@ IA64FAULT vcpu_get_iip(VCPU *vcpu, UINT6 IA64FAULT vcpu_get_ifa(VCPU *vcpu, UINT64 *pval) { - PRIVOP_COUNT_ADDR(vcpu_regs(vcpu),_GET_IFA); + PRIVOP_COUNT_ADDR(vcpu_regs(vcpu), privop_inst_get_ifa); *pval = PSCB(vcpu,ifa); return (IA64_NO_FAULT); } @@ -540,7 +542,7 @@ IA64FAULT vcpu_get_iim(VCPU *vcpu, UINT6 IA64FAULT vcpu_get_iha(VCPU *vcpu, UINT64 *pval) { - PRIVOP_COUNT_ADDR(vcpu_regs(vcpu),_THASH); + PRIVOP_COUNT_ADDR(vcpu_regs(vcpu), privop_inst_thash); *pval = PSCB(vcpu,iha); return (IA64_NO_FAULT); } @@ -2215,3 +2217,28 @@ IA64FAULT vcpu_ptr_i(VCPU *vcpu,UINT64 v return IA64_NO_FAULT; } + +int ia64_map_hypercall_param(void) +{ + struct vcpu *v = current; + struct domain *d = current->domain; + u64 vaddr = v->arch.hypercall_param.va & PAGE_MASK; + volatile pte_t* pte; + + if (v->arch.hypercall_param.va == 0) + return FALSE; + pte = lookup_noalloc_domain_pte(d, v->arch.hypercall_param.pa1); + if (!pte || !pte_present(*pte)) + return FALSE; + vcpu_itc_no_srlz(v, 2, vaddr, pte_val(*pte), -1UL, PAGE_SHIFT); + if (v->arch.hypercall_param.pa2) { + vaddr += PAGE_SIZE; + pte = lookup_noalloc_domain_pte(d, v->arch.hypercall_param.pa2); + if (pte && pte_present(*pte)) { + vcpu_itc_no_srlz(v, 2, vaddr, pte_val(*pte), + -1UL, PAGE_SHIFT); + } + } + ia64_srlz_d(); + return TRUE; +} diff -r e01441c9a607 -r 50aea0ec406b xen/arch/ia64/xen/vhpt.c --- a/xen/arch/ia64/xen/vhpt.c Wed Aug 30 14:09:31 2006 -0500 +++ b/xen/arch/ia64/xen/vhpt.c Wed Aug 30 22:36:18 2006 +0100 @@ -261,13 +261,12 @@ void flush_tlb_mask(cpumask_t mask) (cpu, (void (*)(void *))flush_tlb_vhpt_all, NULL, 1, 1); } -int dump_vhpt_stats(char *buf) +#ifdef PERF_COUNTERS +void gather_vhpt_stats(void) { int i, cpu; - char *s = buf; - - s += sprintf(s,"VHPT usage (%ld entries):\n", - (unsigned long) VHPT_NUM_ENTRIES); + + perfc_set(vhpt_nbr_entries, VHPT_NUM_ENTRIES); for_each_present_cpu (cpu) { struct vhpt_lf_entry *v = __va(per_cpu(vhpt_paddr, cpu)); @@ -276,8 +275,7 @@ int dump_vhpt_stats(char *buf) for (i = 0; i < VHPT_NUM_ENTRIES; i++, v++) if (!(v->ti_tag & INVALID_TI_TAG)) vhpt_valid++; - s += sprintf(s," cpu %d: %ld\n", cpu, vhpt_valid); - } - - return s - buf; -} + perfc_seta(vhpt_valid_entries, cpu, vhpt_valid); + } +} +#endif diff -r e01441c9a607 -r 50aea0ec406b xen/arch/ia64/xen/xen.lds.S --- a/xen/arch/ia64/xen/xen.lds.S Wed Aug 30 14:09:31 2006 -0500 +++ b/xen/arch/ia64/xen/xen.lds.S Wed Aug 30 22:36:18 2006 +0100 @@ -169,7 +169,9 @@ SECTIONS *(.data.gate) __stop_gate_section = .; } - . = ALIGN(PAGE_SIZE); /* make sure the gate page doesn't expose kernel data */ + . = ALIGN(PAGE_SIZE); /* make sure the gate page doesn't expose + * kernel data + */ .data.cacheline_aligned : AT(ADDR(.data.cacheline_aligned) - LOAD_OFFSET) { *(.data.cacheline_aligned) } @@ -184,7 +186,9 @@ SECTIONS *(.data.percpu) __per_cpu_end = .; } - . = __phys_per_cpu_start + PERCPU_PAGE_SIZE; /* ensure percpu data fits into percpu page size */ + . = __phys_per_cpu_start + PERCPU_PAGE_SIZE; /* ensure percpu data fits + * into percpu page size + */ data : { } :data .data : AT(ADDR(.data) - LOAD_OFFSET) diff -r e01441c9a607 -r 50aea0ec406b xen/arch/ia64/xen/xenasm.S --- a/xen/arch/ia64/xen/xenasm.S Wed Aug 30 14:09:31 2006 -0500 +++ b/xen/arch/ia64/xen/xenasm.S Wed Aug 30 22:36:18 2006 +0100 @@ -31,7 +31,7 @@ // loc0=rp, loc1=ar.pfs, loc2=percpu_paddr, loc3=psr, loc4=ar.rse // loc5=pal_vaddr, loc6=xen_paddr, loc7=shared_archinfo_paddr, GLOBAL_ENTRY(ia64_new_rr7) - // not sure this unwind statement is correct... + // FIXME? not sure this unwind statement is correct... .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(1) alloc loc1 = ar.pfs, 5, 8, 0, 0 movl loc2=PERCPU_ADDR @@ -162,7 +162,7 @@ 1: dep r25=0,loc5,60,4 // convert pal vaddr to paddr ;; ptr.i loc5,r23 - or r25=r25,r26 // construct PA | page properties + or r25=r25,r26 // construct PA | page properties mov cr.itir=r23 mov cr.ifa=loc5 ;; @@ -191,10 +191,10 @@ GLOBAL_ENTRY(ia64_prepare_handle_privop) */ mov r16=r0 DO_SAVE_SWITCH_STACK - br.call.sptk.many rp=ia64_handle_privop // stack frame setup in ivt + br.call.sptk.many rp=ia64_handle_privop // stack frame setup in ivt .ret22: .body DO_LOAD_SWITCH_STACK - br.cond.sptk.many rp // goes to ia64_leave_kernel + br.cond.sptk.many rp // goes to ia64_leave_kernel END(ia64_prepare_handle_privop) GLOBAL_ENTRY(ia64_prepare_handle_break) @@ -217,7 +217,7 @@ GLOBAL_ENTRY(ia64_prepare_handle_reflect */ mov r16=r0 DO_SAVE_SWITCH_STACK - br.call.sptk.many rp=ia64_handle_reflection // stack frame setup in ivt + br.call.sptk.many rp=ia64_handle_reflection // stack frame setup in ivt .ret24: .body DO_LOAD_SWITCH_STACK br.cond.sptk.many rp // goes to ia64_leave_kernel @@ -301,7 +301,7 @@ 1: cmp.eq p7,p8=1,r32 /* PAL_CACHE_FLUS (p8) br.cond.sptk.few 1f #if 0 mov r9=ar.lc - movl r8=524288 /* flush 512k million cache lines (16MB) */ + movl r8=524288 /* flush 512k million cache lines (16MB) */ ;; mov ar.lc=r8 movl r8=0xe000000000000000 @@ -319,7 +319,9 @@ 1: cmp.eq p7,p8=15,r32 /* PAL_PERF_MON_ 1: cmp.eq p7,p8=15,r32 /* PAL_PERF_MON_INFO */ (p8) br.cond.sptk.few 1f mov r8=0 /* status = 0 */ - movl r9 =0x08122f04 /* generic=4 width=47 retired=8 cycles=18 */ + movl r9 =0x08122f04 /* generic=4 width=47 retired=8 + * cycles=18 + */ mov r10=0 /* reserved */ mov r11=0 /* reserved */ mov r16=0xffff /* implemented PMC */ @@ -361,8 +363,8 @@ END(pal_emulator_static) END(pal_emulator_static) // These instructions are copied in the domains. -// This is the virtual PAL, which simply does an hypercall. -// The size is 2 bunldes (32 Bytes). It handles both static and stacked +// This is the virtual PAL, which simply does a hypercall. +// The size is 2 bundles (32 Bytes). It handles both static and stacked // convention. // If you modify this code, you have to modify dom_fw.h (for the size) and // dom_fw_pal_hypercall_patch. @@ -376,7 +378,7 @@ GLOBAL_ENTRY(pal_call_stub) } { .mbb - break 0x1000 // Hypercall vector (Value is patched). + break 0x1000 // Hypercall vector (Value is patched). (p7) br.cond.sptk.few rp (p8) br.ret.sptk.few rp } diff -r e01441c9a607 -r 50aea0ec406b xen/arch/ia64/xen/xensetup.c --- a/xen/arch/ia64/xen/xensetup.c Wed Aug 30 14:09:31 2006 -0500 +++ b/xen/arch/ia64/xen/xensetup.c Wed Aug 30 22:36:18 2006 +0100 @@ -26,11 +26,6 @@ #include <linux/efi.h> #include <asm/iosapic.h> -/* Be sure the struct shared_info size is <= XSI_SIZE. */ -#if SHARED_INFO_SIZE > XSI_SIZE -#error "struct shared_info bigger than XSI_SIZE" -#endif - unsigned long xenheap_phys_end, total_pages; char saved_command_line[COMMAND_LINE_SIZE]; @@ -258,6 +253,9 @@ void start_kernel(void) int i; #endif + /* Be sure the struct shared_info size is <= XSI_SIZE. */ + BUILD_BUG_ON(sizeof(struct shared_info) > XSI_SIZE); + running_on_sim = is_platform_hp_ski(); /* Kernel may be relocated by EFI loader */ xen_pstart = ia64_tpa(KERNEL_START); @@ -289,6 +287,7 @@ void start_kernel(void) ia64_boot_param->initrd_size = 0; } + printk("Xen command line: %s\n", saved_command_line); /* xenheap should be in same TR-covered range with xen image */ xenheap_phys_end = xen_pstart + xenheap_size; printk("xen image pstart: 0x%lx, xenheap pend: 0x%lx\n", @@ -518,9 +517,6 @@ printk("num_online_cpus=%d, max_cpus=%d\ 0) != 0) panic("Could not set up DOM0 guest OS\n"); - /* PIN domain0 on CPU 0. */ - dom0->vcpu[0]->cpu_affinity = cpumask_of_cpu(0); - if (!running_on_sim) // slow on ski and pages are pre-initialized to zero scrub_heap_pages(); diff -r e01441c9a607 -r 50aea0ec406b xen/arch/ia64/xen/xentime.c --- a/xen/arch/ia64/xen/xentime.c Wed Aug 30 14:09:31 2006 -0500 +++ b/xen/arch/ia64/xen/xentime.c Wed Aug 30 22:36:18 2006 +0100 @@ -109,6 +109,7 @@ xen_timer_interrupt (int irq, void *dev_ xen_timer_interrupt (int irq, void *dev_id, struct pt_regs *regs) { unsigned long new_itm, old_itc; + int f_setitm = 0; #if 0 #define HEARTBEAT_FREQ 16 // period in seconds @@ -129,11 +130,12 @@ xen_timer_interrupt (int irq, void *dev_ vcpu_pend_timer(current); // ensure another timer interrupt happens even if domain doesn't vcpu_set_next_timer(current); + f_setitm = 1; } new_itm = local_cpu_data->itm_next; - if (!VMX_DOMAIN(current) && !time_after(ia64_get_itc(), new_itm)) + if (f_setitm && !time_after(ia64_get_itc(), new_itm)) return; while (1) { diff -r e01441c9a607 -r 50aea0ec406b xen/arch/x86/physdev.c --- a/xen/arch/x86/physdev.c Wed Aug 30 14:09:31 2006 -0500 +++ b/xen/arch/x86/physdev.c Wed Aug 30 22:36:18 2006 +0100 @@ -96,10 +96,11 @@ long do_physdev_op(int cmd, XEN_GUEST_HA if ( !IS_PRIV(current->domain) ) break; + irq = irq_op.irq; ret = -EINVAL; - if ( (irq = irq_op.irq) >= NR_IRQS ) + if ( (irq < 0) || (irq >= NR_IRQS) ) break; - + irq_op.vector = assign_irq_vector(irq); ret = copy_to_guest(arg, &irq_op, 1) ? -EFAULT : 0; break; diff -r e01441c9a607 -r 50aea0ec406b xen/include/asm-ia64/config.h --- a/xen/include/asm-ia64/config.h Wed Aug 30 14:09:31 2006 -0500 +++ b/xen/include/asm-ia64/config.h Wed Aug 30 22:36:18 2006 +0100 @@ -36,6 +36,12 @@ #define supervisor_mode_kernel (0) #define MAX_DMADOM_PFN (0x7FFFFFFFUL >> PAGE_SHIFT) /* 31 addressable bits */ + +/* If PERFC is used, include privop maps. */ +#ifdef PERF_COUNTERS +#define CONFIG_PRIVOP_ADDRS +#define PRIVOP_COUNT_NADDRS 30 +#endif #define CONFIG_VGA 1 diff -r e01441c9a607 -r 50aea0ec406b xen/include/asm-ia64/dom_fw.h --- a/xen/include/asm-ia64/dom_fw.h Wed Aug 30 14:09:31 2006 -0500 +++ b/xen/include/asm-ia64/dom_fw.h Wed Aug 30 22:36:18 2006 +0100 @@ -7,19 +7,32 @@ #include <linux/efi.h> -#ifndef MB -#define MB (1024*1024) -#endif +/* Portion of guest physical memory space reserved for PAL/SAL/EFI/ACPI + data and code. */ +#define FW_BASE_PADDR 0x0000UL +#define FW_END_PADDR 0x3000UL /* This is used to determined the portion of a domain's metaphysical memory space reserved for the hypercall patch table. */ -//FIXME: experiment with smaller sizes -#define HYPERCALL_START 1UL*MB -#define HYPERCALL_END 2UL*MB +/* Map: + Index Addr + 0x0000-0x000f 0x0000-0x00ff : unused + 0x0010-0x001f 0x0100-0x01ff : EFI + 0x0080-0x008f 0x0800-0x08ff : PAL/SAL + 0x0090-0x009f 0x0900-0x09ff : FPSWA +*/ +#define FW_HYPERCALL_BASE_PADDR 0x0000UL +#define FW_HYPERCALL_END_PADDR 0X1000UL +#define FW_HYPERCALL_PADDR(index) (FW_HYPERCALL_BASE_PADDR + (16UL * index)) -#define FW_HYPERCALL_BASE_PADDR HYPERCALL_START -#define FW_HYPERCALL_END_PADDR HYPERCALL_END -#define FW_HYPERCALL_PADDR(index) (FW_HYPERCALL_BASE_PADDR + (16UL * index)) +/* Base and end guest physical address of ACPI tables. */ +#define FW_ACPI_BASE_PADDR 0x1000UL +#define FW_ACPI_END_PADDR 0x2000UL + +/* Base and end guest physical address of EFI and SAL (non-ACPI) tables. */ +#define FW_TABLES_BASE_PADDR 0x2000UL +#define FW_TABLES_END_PADDR 0x3000UL + /* Hypercalls number have a low part and a high part. The high part is the class (xen/pal/sal/efi). */ @@ -91,16 +104,16 @@ */ /* these are indexes into the runtime services table */ -#define FW_HYPERCALL_EFI_GET_TIME_INDEX 0UL -#define FW_HYPERCALL_EFI_SET_TIME_INDEX 1UL -#define FW_HYPERCALL_EFI_GET_WAKEUP_TIME_INDEX 2UL -#define FW_HYPERCALL_EFI_SET_WAKEUP_TIME_INDEX 3UL -#define FW_HYPERCALL_EFI_SET_VIRTUAL_ADDRESS_MAP_INDEX 4UL -#define FW_HYPERCALL_EFI_GET_VARIABLE_INDEX 5UL -#define FW_HYPERCALL_EFI_GET_NEXT_VARIABLE_INDEX 6UL -#define FW_HYPERCALL_EFI_SET_VARIABLE_INDEX 7UL -#define FW_HYPERCALL_EFI_GET_NEXT_HIGH_MONO_COUNT_INDEX 8UL -#define FW_HYPERCALL_EFI_RESET_SYSTEM_INDEX 9UL +#define FW_HYPERCALL_EFI_GET_TIME_INDEX 0x10UL +#define FW_HYPERCALL_EFI_SET_TIME_INDEX 0x11UL +#define FW_HYPERCALL_EFI_GET_WAKEUP_TIME_INDEX 0x12UL +#define FW_HYPERCALL_EFI_SET_WAKEUP_TIME_INDEX 0x13UL +#define FW_HYPERCALL_EFI_SET_VIRTUAL_ADDRESS_MAP_INDEX 0x14UL +#define FW_HYPERCALL_EFI_GET_VARIABLE_INDEX 0x15UL +#define FW_HYPERCALL_EFI_GET_NEXT_VARIABLE_INDEX 0x16UL +#define FW_HYPERCALL_EFI_SET_VARIABLE_INDEX 0x17UL +#define FW_HYPERCALL_EFI_GET_NEXT_HIGH_MONO_COUNT_INDEX 0x18UL +#define FW_HYPERCALL_EFI_RESET_SYSTEM_INDEX 0x19UL /* these are hypercall numbers */ #define FW_HYPERCALL_EFI_CALL 0x300UL @@ -150,13 +163,10 @@ /* Hypercalls index bellow _FIRST_ARCH are reserved by Xen, while those above are for the architecture. - Note: this limit was defined by Xen/ia64 (and not by Xen).² + Note: this limit was defined by Xen/ia64 (and not by Xen). This can be renumbered safely. */ #define FW_HYPERCALL_FIRST_ARCH 0x300UL - -/* Xen/ia64 user hypercalls. Only used for debugging. */ -#define FW_HYPERCALL_FIRST_USER 0xff00UL /* Interrupt vector used for os boot rendez vous. */ #define XEN_SAL_BOOT_RENDEZ_VEC 0xF3 diff -r e01441c9a607 -r 50aea0ec406b xen/include/asm-ia64/domain.h --- a/xen/include/asm-ia64/domain.h Wed Aug 30 14:09:31 2006 -0500 +++ b/xen/include/asm-ia64/domain.h Wed Aug 30 22:36:18 2006 +0100 @@ -118,8 +118,6 @@ struct arch_domain { /* Address of SAL emulator data */ struct xen_sal_data *sal_data; - /* SAL return point. */ - unsigned long sal_return_addr; /* Address of efi_runtime_services_t (placed in domain memory) */ void *efi_runtime; @@ -137,10 +135,18 @@ struct arch_domain { atomic64_t shadow_fault_count; struct last_vcpu last_vcpu[NR_CPUS]; + + struct arch_vmx_domain arch_vmx; /* Virtual Machine Extensions */ }; #define INT_ENABLE_OFFSET(v) \ (sizeof(vcpu_info_t) * (v)->vcpu_id + \ offsetof(vcpu_info_t, evtchn_upcall_mask)) + +struct hypercall_param { + unsigned long va; + unsigned long pa1; + unsigned long pa2; +}; struct arch_vcpu { /* Save the state of vcpu. @@ -185,10 +191,14 @@ struct arch_vcpu { char irq_new_pending; char irq_new_condition; // vpsr.i/vtpr change, check for pending VHPI char hypercall_continuation; + + struct hypercall_param hypercall_param; // used to remap a hypercall param + //for phycial emulation unsigned long old_rsc; int mode_flags; fpswa_ret_t fpswa_ret; /* save return values of FPSWA emulation */ + struct timer hlt_timer; struct arch_vmx_struct arch_vmx; /* Virtual Machine Extensions */ #define INVALID_PROCESSOR INT_MAX diff -r e01441c9a607 -r 50aea0ec406b xen/include/asm-ia64/grant_table.h --- a/xen/include/asm-ia64/grant_table.h Wed Aug 30 14:09:31 2006 -0500 +++ b/xen/include/asm-ia64/grant_table.h Wed Aug 30 22:36:18 2006 +0100 @@ -35,7 +35,7 @@ void guest_physmap_add_page(struct domai gnttab_shared_maddr((d), (t), (i))); \ (IA64_GRANT_TABLE_PADDR >> PAGE_SHIFT) + (i);}) -#define gnttab_log_dirty(d, f) ((void)0) +#define gnttab_mark_dirty(d, f) ((void)f) static inline void gnttab_clear_flag(unsigned long nr, uint16_t *addr) { diff -r e01441c9a607 -r 50aea0ec406b xen/include/asm-ia64/linux-xen/asm/processor.h --- a/xen/include/asm-ia64/linux-xen/asm/processor.h Wed Aug 30 14:09:31 2006 -0500 +++ b/xen/include/asm-ia64/linux-xen/asm/processor.h Wed Aug 30 22:36:18 2006 +0100 @@ -717,6 +717,14 @@ prefetchw (const void *x) extern unsigned long boot_option_idle_override; +#ifdef XEN +static inline unsigned int +ia64_get_cpl(unsigned long psr) +{ + return (psr & IA64_PSR_CPL) >> IA64_PSR_CPL0_BIT; +} +#endif + #endif /* !__ASSEMBLY__ */ #endif /* _ASM_IA64_PROCESSOR_H */ diff -r e01441c9a607 -r 50aea0ec406b xen/include/asm-ia64/linux-xen/linux/efi.h --- a/xen/include/asm-ia64/linux-xen/linux/efi.h Wed Aug 30 14:09:31 2006 -0500 +++ b/xen/include/asm-ia64/linux-xen/linux/efi.h Wed Aug 30 22:36:18 2006 +0100 @@ -293,10 +293,6 @@ extern void efi_map_pal_code (void); extern void efi_map_pal_code (void); extern void efi_map_memmap(void); extern void efi_memmap_walk (efi_freemem_callback_t callback, void *arg); -#ifdef XEN -typedef int (*efi_walk_type_callback_t)(efi_memory_desc_t *md, void *arg); -extern void efi_memmap_walk_type(u32 type, efi_walk_type_callback_t callback, void *arg); -#endif extern void efi_gettimeofday (struct timespec *ts); extern void efi_enter_virtual_mode (void); /* switch EFI to virtual mode, if possible */ extern u64 efi_get_iobase (void); diff -r e01441c9a607 -r 50aea0ec406b xen/include/asm-ia64/multicall.h --- a/xen/include/asm-ia64/multicall.h Wed Aug 30 14:09:31 2006 -0500 +++ b/xen/include/asm-ia64/multicall.h Wed Aug 30 22:36:18 2006 +0100 @@ -2,6 +2,7 @@ #define __ASM_IA64_MULTICALL_H__ #include <public/xen.h> +#include <xen/errno.h> typedef unsigned long (*hypercall_t)( unsigned long arg0, @@ -11,17 +12,20 @@ typedef unsigned long (*hypercall_t)( unsigned long arg4, unsigned long arg5); -extern hypercall_t ia64_hypercall_table[]; +extern const hypercall_t ia64_hypercall_table[]; static inline void do_multicall_call(multicall_entry_t *call) { - call->result = (*ia64_hypercall_table[call->op])( + if (call->op < NR_hypercalls) + call->result = (*ia64_hypercall_table[call->op])( call->args[0], call->args[1], call->args[2], call->args[3], call->args[4], call->args[5]); + else + call->result = -ENOSYS; } #endif /* __ASM_IA64_MULTICALL_H__ */ diff -r e01441c9a607 -r 50aea0ec406b xen/include/asm-ia64/perfc.h --- a/xen/include/asm-ia64/perfc.h Wed Aug 30 14:09:31 2006 -0500 +++ b/xen/include/asm-ia64/perfc.h Wed Aug 30 22:36:18 2006 +0100 @@ -1,16 +1,22 @@ #ifndef __ASM_PERFC_H__ #define __ASM_PERFC_H__ -static inline void arch_perfc_printall (void) +#include <asm/vhpt.h> +#include <asm/privop_stat.h> + +static inline void arch_perfc_printall(void) { } -static inline void arch_perfc_reset (void) +static inline void arch_perfc_reset(void) { + reset_privop_addrs(); } -static inline void arch_perfc_gather (void) +static inline void arch_perfc_gather(void) { + gather_vhpt_stats(); + gather_privop_addrs(); } #endif diff -r e01441c9a607 -r 50aea0ec406b xen/include/asm-ia64/perfc_defn.h --- a/xen/include/asm-ia64/perfc_defn.h Wed Aug 30 14:09:31 2006 -0500 +++ b/xen/include/asm-ia64/perfc_defn.h Wed Aug 30 22:36:18 2006 +0100 @@ -40,3 +40,20 @@ PERFCOUNTER_ARRAY(fast_hyperprivop, "f PERFCOUNTER_ARRAY(slow_reflect, "slow reflection", 0x80) PERFCOUNTER_ARRAY(fast_reflect, "fast reflection", 0x80) + +PERFSTATUS(vhpt_nbr_entries, "nbr of entries per VHPT") +PERFSTATUS_CPU(vhpt_valid_entries, "nbr of valid entries in VHPT") + +#ifdef CONFIG_PRIVOP_ADDRS +#ifndef PERFPRIVOPADDR +#define PERFPRIVOPADDR(name) \ +PERFSTATUS_ARRAY(privop_addr_##name##_addr, "privop-addrs addr " #name, \ + PRIVOP_COUNT_NADDRS) \ +PERFSTATUS_ARRAY(privop_addr_##name##_count, "privop-addrs count " #name, \ + PRIVOP_COUNT_NADDRS) \ +PERFSTATUS(privop_addr_##name##_overflow, "privop-addrs overflow " #name) +#endif + +PERFPRIVOPADDR(get_ifa) +PERFPRIVOPADDR(thash) +#endif diff -r e01441c9a607 -r 50aea0ec406b xen/include/asm-ia64/privop_stat.h --- a/xen/include/asm-ia64/privop_stat.h Wed Aug 30 14:09:31 2006 -0500 +++ b/xen/include/asm-ia64/privop_stat.h Wed Aug 30 22:36:18 2006 +0100 @@ -1,23 +1,48 @@ #ifndef _XEN_UA64_PRIVOP_STAT_H #define _XEN_UA64_PRIVOP_STAT_H +#include <asm/config.h> #include <xen/types.h> #include <public/xen.h> -extern int dump_privop_counts_to_user(char *, int); -extern int zero_privop_counts_to_user(char *, int); +#ifdef CONFIG_PRIVOP_ADDRS -#define PRIVOP_ADDR_COUNT +extern void gather_privop_addrs(void); +extern void reset_privop_addrs(void); -#ifdef PRIVOP_ADDR_COUNT +#undef PERFCOUNTER +#define PERFCOUNTER(var, name) -/* INST argument of PRIVOP_COUNT_ADDR. */ -#define _GET_IFA 0 -#define _THASH 1 +#undef PERFCOUNTER_CPU +#define PERFCOUNTER_CPU(var, name) + +#undef PERFCOUNTER_ARRAY +#define PERFCOUNTER_ARRAY(var, name, size) + +#undef PERFSTATUS +#define PERFSTATUS(var, name) + +#undef PERFSTATUS_CPU +#define PERFSTATUS_CPU(var, name) + +#undef PERFSTATUS_ARRAY +#define PERFSTATUS_ARRAY(var, name, size) + +#undef PERFPRIVOPADDR +#define PERFPRIVOPADDR(name) privop_inst_##name, + +enum privop_inst { +#include <asm/perfc_defn.h> +}; + +#undef PERFPRIVOPADDR + #define PRIVOP_COUNT_ADDR(regs,inst) privop_count_addr(regs->cr_iip,inst) -extern void privop_count_addr(unsigned long addr, int inst); +extern void privop_count_addr(unsigned long addr, enum privop_inst inst); #else -#define PRIVOP_COUNT_ADDR(x,y) do {} while (0) +#define PRIVOP_COUNT_ADDR(x,y) do {} while (0) +#define gather_privop_addrs() do {} while (0) +#define reset_privop_addrs() do {} while (0) #endif #endif /* _XEN_UA64_PRIVOP_STAT_H */ diff -r e01441c9a607 -r 50aea0ec406b xen/include/asm-ia64/uaccess.h --- a/xen/include/asm-ia64/uaccess.h Wed Aug 30 14:09:31 2006 -0500 +++ b/xen/include/asm-ia64/uaccess.h Wed Aug 30 22:36:18 2006 +0100 @@ -211,16 +211,30 @@ extern unsigned long __must_check __copy extern unsigned long __must_check __copy_user (void __user *to, const void __user *from, unsigned long count); +extern int ia64_map_hypercall_param(void); + static inline unsigned long __copy_to_user (void __user *to, const void *from, unsigned long count) { - return __copy_user(to, (void __user *) from, count); + unsigned long len; + len = __copy_user(to, (void __user *)from, count); + if (len == 0) + return 0; + if (ia64_map_hypercall_param()) + len = __copy_user(to, (void __user *)from, count); /* retry */ + return len; } static inline unsigned long __copy_from_user (void *to, const void __user *from, unsigned long count) { - return __copy_user((void __user *) to, from, count); + unsigned long len; + len = __copy_user((void __user *)to, from, count); + if (len == 0) + return 0; + if (ia64_map_hypercall_param()) + len = __copy_user((void __user *) to, from, count); /* retry */ + return len; } #define __copy_to_user_inatomic __copy_to_user diff -r e01441c9a607 -r 50aea0ec406b xen/include/asm-ia64/vcpu.h --- a/xen/include/asm-ia64/vcpu.h Wed Aug 30 14:09:31 2006 -0500 +++ b/xen/include/asm-ia64/vcpu.h Wed Aug 30 22:36:18 2006 +0100 @@ -4,6 +4,7 @@ // TODO: Many (or perhaps most) of these should eventually be // static inline functions +#include <asm/delay.h> #include <asm/fpu.h> #include <asm/tlb.h> #include <asm/ia64_int.h> @@ -15,6 +16,7 @@ struct vcpu; struct vcpu; typedef struct vcpu VCPU; typedef cpu_user_regs_t REGS; +extern u64 cycle_to_ns(u64 cycle); /* Note: PSCB stands for Privilegied State Communication Block. */ #define VCPU(_v,_x) (_v->arch.privregs->_x) @@ -183,6 +185,21 @@ itir_mask(UINT64 itir) return (~((1UL << itir_ps(itir)) - 1)); } +static inline s64 +vcpu_get_next_timer_ns(VCPU *vcpu) +{ + s64 vcpu_get_next_timer_ns; + u64 d = PSCBX(vcpu, domain_itm); + u64 now = ia64_get_itc(); + + if (d > now) + vcpu_get_next_timer_ns = cycle_to_ns(d - now) + NOW(); + else + vcpu_get_next_timer_ns = cycle_to_ns(local_cpu_data->itm_delta) + NOW(); + + return vcpu_get_next_timer_ns; +} + #define verbose(a...) do {if (vcpu_verbose) printf(a);} while(0) //#define vcpu_quick_region_check(_tr_regions,_ifa) 1 diff -r e01441c9a607 -r 50aea0ec406b xen/include/asm-ia64/vhpt.h --- a/xen/include/asm-ia64/vhpt.h Wed Aug 30 14:09:31 2006 -0500 +++ b/xen/include/asm-ia64/vhpt.h Wed Aug 30 22:36:18 2006 +0100 @@ -32,7 +32,7 @@ struct vhpt_lf_entry { #define INVALID_TI_TAG 0x8000000000000000L extern void vhpt_init (void); -extern int dump_vhpt_stats(char *buf); +extern void gather_vhpt_stats(void); extern void vhpt_multiple_insert(unsigned long vaddr, unsigned long pte, unsigned long logps); extern void vhpt_insert (unsigned long vadr, unsigned long pte, diff -r e01441c9a607 -r 50aea0ec406b xen/include/asm-ia64/vmx.h --- a/xen/include/asm-ia64/vmx.h Wed Aug 30 14:09:31 2006 -0500 +++ b/xen/include/asm-ia64/vmx.h Wed Aug 30 22:36:18 2006 +0100 @@ -35,7 +35,6 @@ extern void vmx_save_state(struct vcpu * extern void vmx_save_state(struct vcpu *v); extern void vmx_load_state(struct vcpu *v); extern void vmx_setup_platform(struct domain *d); -extern void vmx_wait_io(void); extern void vmx_io_assist(struct vcpu *v); extern int ia64_hypercall (struct pt_regs *regs); extern void vmx_save_state(struct vcpu *v); @@ -53,17 +52,14 @@ extern void vmx_intr_assist(struct vcpu extern void vmx_intr_assist(struct vcpu *v); extern void set_illegal_op_isr (struct vcpu *vcpu); extern void illegal_op (struct vcpu *vcpu); +extern void vmx_relinquish_guest_resources(struct domain *d); extern void vmx_relinquish_vcpu_resources(struct vcpu *v); extern void vmx_die_if_kernel(char *str, struct pt_regs *regs, long err); +extern void vmx_send_assist_req(struct vcpu *v); static inline vcpu_iodata_t *get_vio(struct domain *d, unsigned long cpu) { return &((shared_iopage_t *)d->arch.vmx_platform.shared_page_va)->vcpu_iodata[cpu]; -} - -static inline int iopacket_port(struct vcpu *v) -{ - return get_vio(v->domain, v->vcpu_id)->vp_eport; } static inline shared_iopage_t *get_sp(struct domain *d) diff -r e01441c9a607 -r 50aea0ec406b xen/include/asm-ia64/vmx_vcpu.h --- a/xen/include/asm-ia64/vmx_vcpu.h Wed Aug 30 14:09:31 2006 -0500 +++ b/xen/include/asm-ia64/vmx_vcpu.h Wed Aug 30 22:36:18 2006 +0100 @@ -239,12 +239,13 @@ vmx_vcpu_set_dcr(VCPU *vcpu, u64 val) { u64 mdcr, mask; VCPU(vcpu,dcr)=val; - /* All vDCR bits will go to mDCR, except for be/pp bit */ + /* All vDCR bits will go to mDCR, except for be/pp/dm bits */ mdcr = ia64_get_dcr(); - mask = IA64_DCR_BE | IA64_DCR_PP; + /* Machine dcr.dm masked to handle guest ld.s on tr mapped page */ + mask = IA64_DCR_BE | IA64_DCR_PP | IA64_DCR_DM; mdcr = ( mdcr & mask ) | ( val & (~mask) ); ia64_set_dcr( mdcr); - + VMX(vcpu, mdcr) = mdcr; return IA64_NO_FAULT; } diff -r e01441c9a607 -r 50aea0ec406b xen/include/asm-ia64/vmx_vpd.h --- a/xen/include/asm-ia64/vmx_vpd.h Wed Aug 30 14:09:31 2006 -0500 +++ b/xen/include/asm-ia64/vmx_vpd.h Wed Aug 30 22:36:18 2006 +0100 @@ -27,6 +27,7 @@ #include <asm/vtm.h> #include <asm/vmx_platform.h> #include <public/xen.h> +#include <xen/spinlock.h> #define VPD_SHIFT 17 /* 128K requirement */ #define VPD_SIZE (1 << VPD_SHIFT) @@ -72,6 +73,11 @@ struct ivt_debug{ }; #define IVT_DEBUG_MAX 128 #endif + +struct arch_vmx_domain { + spinlock_t virq_assist_lock; /* spinlock for pass virq */ +}; + struct arch_vmx_struct { // vpd_t *vpd; vtime_t vtm; @@ -89,13 +95,15 @@ struct arch_vmx_struct { // unsigned long mrr5; // unsigned long mrr6; // unsigned long mrr7; + unsigned long mdcr; unsigned long mpta; // unsigned long rfi_pfs; // unsigned long rfi_iip; // unsigned long rfi_ipsr; // unsigned long rfi_ifs; // unsigned long in_service[4]; // vLsapic inservice IRQ bits - unsigned long flags; + unsigned long flags; + unsigned long xen_port; #ifdef VTI_DEBUG unsigned long ivt_current; struct ivt_debug ivt_debug[IVT_DEBUG_MAX]; diff -r e01441c9a607 -r 50aea0ec406b xen/include/public/domctl.h --- a/xen/include/public/domctl.h Wed Aug 30 14:09:31 2006 -0500 +++ b/xen/include/public/domctl.h Wed Aug 30 22:36:18 2006 +0100 @@ -16,7 +16,7 @@ #include "xen.h" -#define XEN_DOMCTL_INTERFACE_VERSION 0x00000001 +#define XEN_DOMCTL_INTERFACE_VERSION 0x00000002 #define uint64_t uint64_aligned_t @@ -72,8 +72,11 @@ DEFINE_XEN_GUEST_HANDLE(xen_domctl_getdo #define XEN_DOMCTL_getmemlist 6 struct xen_domctl_getmemlist { /* IN variables. */ + /* Max entries to write to output buffer. */ uint64_t max_pfns; - XEN_GUEST_HANDLE_64(ulong) buffer; + /* Start index in guest's page list. */ + uint64_t start_pfn; + XEN_GUEST_HANDLE_64(xen_pfn_t) buffer; /* OUT variables. */ uint64_t num_pfns; }; diff -r e01441c9a607 -r 50aea0ec406b xen/include/public/xen.h --- a/xen/include/public/xen.h Wed Aug 30 14:09:31 2006 -0500 +++ b/xen/include/public/xen.h Wed Aug 30 22:36:18 2006 +0100 @@ -63,6 +63,7 @@ #define __HYPERVISOR_hvm_op 34 #define __HYPERVISOR_sysctl 35 #define __HYPERVISOR_domctl 36 +#define __HYPERVISOR_kexec_op 37 /* Architecture-specific hypercall definitions. */ #define __HYPERVISOR_arch_0 48 diff -r e01441c9a607 -r 50aea0ec406b linux-2.6-xen-sparse/include/asm-ia64/maddr.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/linux-2.6-xen-sparse/include/asm-ia64/maddr.h Wed Aug 30 22:36:18 2006 +0100 @@ -0,0 +1,88 @@ +#ifndef _ASM_IA64_MADDR_H +#define _ASM_IA64_MADDR_H + +#include <linux/kernel.h> +#include <asm/hypervisor.h> +#include <xen/features.h> +#include <xen/interface/xen.h> + +#ifdef CONFIG_XEN + +#define INVALID_P2M_ENTRY (~0UL) + +/* XXX xen page size != page size */ +static inline unsigned long +pfn_to_mfn_for_dma(unsigned long pfn) +{ + unsigned long mfn; + mfn = HYPERVISOR_phystomach(pfn); + BUG_ON(mfn == 0); // XXX + BUG_ON(mfn == INVALID_P2M_ENTRY); // XXX + BUG_ON(mfn == INVALID_MFN); + return mfn; +} + +static inline unsigned long +phys_to_machine_for_dma(unsigned long phys) +{ + unsigned long machine = + pfn_to_mfn_for_dma(phys >> PAGE_SHIFT) << PAGE_SHIFT; + machine |= (phys & ~PAGE_MASK); + return machine; +} + +static inline unsigned long +mfn_to_pfn_for_dma(unsigned long mfn) +{ + unsigned long pfn; + pfn = HYPERVISOR_machtophys(mfn); + BUG_ON(pfn == 0); + //BUG_ON(pfn == INVALID_M2P_ENTRY); + return pfn; +} + +static inline unsigned long +machine_to_phys_for_dma(unsigned long machine) +{ + unsigned long phys = + mfn_to_pfn_for_dma(machine >> PAGE_SHIFT) << PAGE_SHIFT; + phys |= (machine & ~PAGE_MASK); + return phys; +} + +static inline unsigned long +mfn_to_local_pfn(unsigned long mfn) +{ + extern unsigned long max_mapnr; + unsigned long pfn = mfn_to_pfn_for_dma(mfn); + if (!pfn_valid(pfn)) + return INVALID_P2M_ENTRY; + return pfn; +} + +#else /* !CONFIG_XEN */ + +#define pfn_to_mfn_for_dma(pfn) (pfn) +#define mfn_to_pfn_for_dma(mfn) (mfn) +#define phys_to_machine_for_dma(phys) (phys) +#define machine_to_phys_for_dma(machine) (machine) +#define mfn_to_local_pfn(mfn) (mfn) + +#endif /* !CONFIG_XEN */ + +/* XXX to compile set_phys_to_machine(vaddr, FOREIGN_FRAME(m)) */ +#define FOREIGN_FRAME(m) (INVALID_P2M_ENTRY) + +#define mfn_to_pfn(mfn) (mfn) +#define pfn_to_mfn(pfn) (pfn) + +#define mfn_to_virt(mfn) (__va((mfn) << PAGE_SHIFT)) +#define virt_to_mfn(virt) (__pa(virt) >> PAGE_SHIFT) +#define virt_to_machine(virt) __pa(virt) // for tpmfront.c + +#define set_phys_to_machine(pfn, mfn) do { } while (0) +#define xen_machphys_update(mfn, pfn) do { } while (0) + +typedef unsigned long maddr_t; // to compile netback, netfront + +#endif /* _ASM_IA64_MADDR_H */ _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |