diff options
| -rw-r--r-- | arch/arm/xen/enlighten.c | 11 | ||||
| -rw-r--r-- | arch/x86/xen/mmu.c | 60 | ||||
| -rw-r--r-- | arch/x86/xen/xen-pvh.S | 47 | ||||
| -rw-r--r-- | drivers/net/xen-netfront.c | 2 | ||||
| -rw-r--r-- | drivers/xen/privcmd.c | 135 | ||||
| -rw-r--r-- | drivers/xen/xenbus/xenbus_probe.c | 5 | ||||
| -rw-r--r-- | include/uapi/xen/privcmd.h | 11 | ||||
| -rw-r--r-- | include/xen/interface/memory.h | 66 | ||||
| -rw-r--r-- | include/xen/interface/xen.h | 7 | ||||
| -rw-r--r-- | include/xen/xen-ops.h | 24 |
10 files changed, 332 insertions, 36 deletions
diff --git a/arch/arm/xen/enlighten.c b/arch/arm/xen/enlighten.c index ba7f4c8f5c3e..8073625371f5 100644 --- a/arch/arm/xen/enlighten.c +++ b/arch/arm/xen/enlighten.c | |||
| @@ -89,6 +89,17 @@ int xen_unmap_domain_gfn_range(struct vm_area_struct *vma, | |||
| 89 | } | 89 | } |
| 90 | EXPORT_SYMBOL_GPL(xen_unmap_domain_gfn_range); | 90 | EXPORT_SYMBOL_GPL(xen_unmap_domain_gfn_range); |
| 91 | 91 | ||
| 92 | /* Not used by XENFEAT_auto_translated guests. */ | ||
| 93 | int xen_remap_domain_mfn_array(struct vm_area_struct *vma, | ||
| 94 | unsigned long addr, | ||
| 95 | xen_pfn_t *mfn, int nr, | ||
| 96 | int *err_ptr, pgprot_t prot, | ||
| 97 | unsigned int domid, struct page **pages) | ||
| 98 | { | ||
| 99 | return -ENOSYS; | ||
| 100 | } | ||
| 101 | EXPORT_SYMBOL_GPL(xen_remap_domain_mfn_array); | ||
| 102 | |||
| 92 | static void xen_read_wallclock(struct timespec64 *ts) | 103 | static void xen_read_wallclock(struct timespec64 *ts) |
| 93 | { | 104 | { |
| 94 | u32 version; | 105 | u32 version; |
diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c index 2d76106788a3..96fc2f0fdbfe 100644 --- a/arch/x86/xen/mmu.c +++ b/arch/x86/xen/mmu.c | |||
| @@ -63,37 +63,44 @@ static noinline void xen_flush_tlb_all(void) | |||
| 63 | #define REMAP_BATCH_SIZE 16 | 63 | #define REMAP_BATCH_SIZE 16 |
| 64 | 64 | ||
| 65 | struct remap_data { | 65 | struct remap_data { |
| 66 | xen_pfn_t *mfn; | 66 | xen_pfn_t *pfn; |
| 67 | bool contiguous; | 67 | bool contiguous; |
| 68 | bool no_translate; | ||
| 68 | pgprot_t prot; | 69 | pgprot_t prot; |
| 69 | struct mmu_update *mmu_update; | 70 | struct mmu_update *mmu_update; |
| 70 | }; | 71 | }; |
| 71 | 72 | ||
| 72 | static int remap_area_mfn_pte_fn(pte_t *ptep, pgtable_t token, | 73 | static int remap_area_pfn_pte_fn(pte_t *ptep, pgtable_t token, |
| 73 | unsigned long addr, void *data) | 74 | unsigned long addr, void *data) |
| 74 | { | 75 | { |
| 75 | struct remap_data *rmd = data; | 76 | struct remap_data *rmd = data; |
| 76 | pte_t pte = pte_mkspecial(mfn_pte(*rmd->mfn, rmd->prot)); | 77 | pte_t pte = pte_mkspecial(mfn_pte(*rmd->pfn, rmd->prot)); |
| 77 | 78 | ||
| 78 | /* If we have a contiguous range, just update the mfn itself, | 79 | /* |
| 79 | else update pointer to be "next mfn". */ | 80 | * If we have a contiguous range, just update the pfn itself, |
| 81 | * else update pointer to be "next pfn". | ||
| 82 | */ | ||
| 80 | if (rmd->contiguous) | 83 | if (rmd->contiguous) |
| 81 | (*rmd->mfn)++; | 84 | (*rmd->pfn)++; |
| 82 | else | 85 | else |
| 83 | rmd->mfn++; | 86 | rmd->pfn++; |
| 84 | 87 | ||
| 85 | rmd->mmu_update->ptr = virt_to_machine(ptep).maddr | MMU_NORMAL_PT_UPDATE; | 88 | rmd->mmu_update->ptr = virt_to_machine(ptep).maddr; |
| 89 | rmd->mmu_update->ptr |= rmd->no_translate ? | ||
| 90 | MMU_PT_UPDATE_NO_TRANSLATE : | ||
| 91 | MMU_NORMAL_PT_UPDATE; | ||
| 86 | rmd->mmu_update->val = pte_val_ma(pte); | 92 | rmd->mmu_update->val = pte_val_ma(pte); |
| 87 | rmd->mmu_update++; | 93 | rmd->mmu_update++; |
| 88 | 94 | ||
| 89 | return 0; | 95 | return 0; |
| 90 | } | 96 | } |
| 91 | 97 | ||
| 92 | static int do_remap_gfn(struct vm_area_struct *vma, | 98 | static int do_remap_pfn(struct vm_area_struct *vma, |
| 93 | unsigned long addr, | 99 | unsigned long addr, |
| 94 | xen_pfn_t *gfn, int nr, | 100 | xen_pfn_t *pfn, int nr, |
| 95 | int *err_ptr, pgprot_t prot, | 101 | int *err_ptr, pgprot_t prot, |
| 96 | unsigned domid, | 102 | unsigned int domid, |
| 103 | bool no_translate, | ||
| 97 | struct page **pages) | 104 | struct page **pages) |
| 98 | { | 105 | { |
| 99 | int err = 0; | 106 | int err = 0; |
| @@ -104,11 +111,14 @@ static int do_remap_gfn(struct vm_area_struct *vma, | |||
| 104 | 111 | ||
| 105 | BUG_ON(!((vma->vm_flags & (VM_PFNMAP | VM_IO)) == (VM_PFNMAP | VM_IO))); | 112 | BUG_ON(!((vma->vm_flags & (VM_PFNMAP | VM_IO)) == (VM_PFNMAP | VM_IO))); |
| 106 | 113 | ||
| 107 | rmd.mfn = gfn; | 114 | rmd.pfn = pfn; |
| 108 | rmd.prot = prot; | 115 | rmd.prot = prot; |
| 109 | /* We use the err_ptr to indicate if there we are doing a contiguous | 116 | /* |
| 110 | * mapping or a discontigious mapping. */ | 117 | * We use the err_ptr to indicate if there we are doing a contiguous |
| 118 | * mapping or a discontigious mapping. | ||
| 119 | */ | ||
| 111 | rmd.contiguous = !err_ptr; | 120 | rmd.contiguous = !err_ptr; |
| 121 | rmd.no_translate = no_translate; | ||
| 112 | 122 | ||
| 113 | while (nr) { | 123 | while (nr) { |
| 114 | int index = 0; | 124 | int index = 0; |
| @@ -119,7 +129,7 @@ static int do_remap_gfn(struct vm_area_struct *vma, | |||
| 119 | 129 | ||
| 120 | rmd.mmu_update = mmu_update; | 130 | rmd.mmu_update = mmu_update; |
| 121 | err = apply_to_page_range(vma->vm_mm, addr, range, | 131 | err = apply_to_page_range(vma->vm_mm, addr, range, |
| 122 | remap_area_mfn_pte_fn, &rmd); | 132 | remap_area_pfn_pte_fn, &rmd); |
| 123 | if (err) | 133 | if (err) |
| 124 | goto out; | 134 | goto out; |
| 125 | 135 | ||
| @@ -173,7 +183,8 @@ int xen_remap_domain_gfn_range(struct vm_area_struct *vma, | |||
| 173 | if (xen_feature(XENFEAT_auto_translated_physmap)) | 183 | if (xen_feature(XENFEAT_auto_translated_physmap)) |
| 174 | return -EOPNOTSUPP; | 184 | return -EOPNOTSUPP; |
| 175 | 185 | ||
| 176 | return do_remap_gfn(vma, addr, &gfn, nr, NULL, prot, domid, pages); | 186 | return do_remap_pfn(vma, addr, &gfn, nr, NULL, prot, domid, false, |
| 187 | pages); | ||
| 177 | } | 188 | } |
| 178 | EXPORT_SYMBOL_GPL(xen_remap_domain_gfn_range); | 189 | EXPORT_SYMBOL_GPL(xen_remap_domain_gfn_range); |
| 179 | 190 | ||
| @@ -192,10 +203,25 @@ int xen_remap_domain_gfn_array(struct vm_area_struct *vma, | |||
| 192 | * cause of "wrong memory was mapped in". | 203 | * cause of "wrong memory was mapped in". |
| 193 | */ | 204 | */ |
| 194 | BUG_ON(err_ptr == NULL); | 205 | BUG_ON(err_ptr == NULL); |
| 195 | return do_remap_gfn(vma, addr, gfn, nr, err_ptr, prot, domid, pages); | 206 | return do_remap_pfn(vma, addr, gfn, nr, err_ptr, prot, domid, |
| 207 | false, pages); | ||
| 196 | } | 208 | } |
| 197 | EXPORT_SYMBOL_GPL(xen_remap_domain_gfn_array); | 209 | EXPORT_SYMBOL_GPL(xen_remap_domain_gfn_array); |
| 198 | 210 | ||
| 211 | int xen_remap_domain_mfn_array(struct vm_area_struct *vma, | ||
| 212 | unsigned long addr, | ||
| 213 | xen_pfn_t *mfn, int nr, | ||
| 214 | int *err_ptr, pgprot_t prot, | ||
| 215 | unsigned int domid, struct page **pages) | ||
| 216 | { | ||
| 217 | if (xen_feature(XENFEAT_auto_translated_physmap)) | ||
| 218 | return -EOPNOTSUPP; | ||
| 219 | |||
| 220 | return do_remap_pfn(vma, addr, mfn, nr, err_ptr, prot, domid, | ||
| 221 | true, pages); | ||
| 222 | } | ||
| 223 | EXPORT_SYMBOL_GPL(xen_remap_domain_mfn_array); | ||
| 224 | |||
| 199 | /* Returns: 0 success */ | 225 | /* Returns: 0 success */ |
| 200 | int xen_unmap_domain_gfn_range(struct vm_area_struct *vma, | 226 | int xen_unmap_domain_gfn_range(struct vm_area_struct *vma, |
| 201 | int nr, struct page **pages) | 227 | int nr, struct page **pages) |
diff --git a/arch/x86/xen/xen-pvh.S b/arch/x86/xen/xen-pvh.S index e1a5fbeae08d..ca2d3b2bf2af 100644 --- a/arch/x86/xen/xen-pvh.S +++ b/arch/x86/xen/xen-pvh.S | |||
| @@ -54,12 +54,19 @@ | |||
| 54 | * charge of setting up it's own stack, GDT and IDT. | 54 | * charge of setting up it's own stack, GDT and IDT. |
| 55 | */ | 55 | */ |
| 56 | 56 | ||
| 57 | #define PVH_GDT_ENTRY_CS 1 | ||
| 58 | #define PVH_GDT_ENTRY_DS 2 | ||
| 59 | #define PVH_GDT_ENTRY_CANARY 3 | ||
| 60 | #define PVH_CS_SEL (PVH_GDT_ENTRY_CS * 8) | ||
| 61 | #define PVH_DS_SEL (PVH_GDT_ENTRY_DS * 8) | ||
| 62 | #define PVH_CANARY_SEL (PVH_GDT_ENTRY_CANARY * 8) | ||
| 63 | |||
| 57 | ENTRY(pvh_start_xen) | 64 | ENTRY(pvh_start_xen) |
| 58 | cld | 65 | cld |
| 59 | 66 | ||
| 60 | lgdt (_pa(gdt)) | 67 | lgdt (_pa(gdt)) |
| 61 | 68 | ||
| 62 | mov $(__BOOT_DS),%eax | 69 | mov $PVH_DS_SEL,%eax |
| 63 | mov %eax,%ds | 70 | mov %eax,%ds |
| 64 | mov %eax,%es | 71 | mov %eax,%es |
| 65 | mov %eax,%ss | 72 | mov %eax,%ss |
| @@ -93,11 +100,17 @@ ENTRY(pvh_start_xen) | |||
| 93 | mov %eax, %cr0 | 100 | mov %eax, %cr0 |
| 94 | 101 | ||
| 95 | /* Jump to 64-bit mode. */ | 102 | /* Jump to 64-bit mode. */ |
| 96 | ljmp $__KERNEL_CS, $_pa(1f) | 103 | ljmp $PVH_CS_SEL, $_pa(1f) |
| 97 | 104 | ||
| 98 | /* 64-bit entry point. */ | 105 | /* 64-bit entry point. */ |
| 99 | .code64 | 106 | .code64 |
| 100 | 1: | 107 | 1: |
| 108 | /* Set base address in stack canary descriptor. */ | ||
| 109 | mov $MSR_GS_BASE,%ecx | ||
| 110 | mov $_pa(canary), %eax | ||
| 111 | xor %edx, %edx | ||
| 112 | wrmsr | ||
| 113 | |||
| 101 | call xen_prepare_pvh | 114 | call xen_prepare_pvh |
| 102 | 115 | ||
| 103 | /* startup_64 expects boot_params in %rsi. */ | 116 | /* startup_64 expects boot_params in %rsi. */ |
| @@ -107,6 +120,17 @@ ENTRY(pvh_start_xen) | |||
| 107 | 120 | ||
| 108 | #else /* CONFIG_X86_64 */ | 121 | #else /* CONFIG_X86_64 */ |
| 109 | 122 | ||
| 123 | /* Set base address in stack canary descriptor. */ | ||
| 124 | movl $_pa(gdt_start),%eax | ||
| 125 | movl $_pa(canary),%ecx | ||
| 126 | movw %cx, (PVH_GDT_ENTRY_CANARY * 8) + 2(%eax) | ||
| 127 | shrl $16, %ecx | ||
| 128 | movb %cl, (PVH_GDT_ENTRY_CANARY * 8) + 4(%eax) | ||
| 129 | movb %ch, (PVH_GDT_ENTRY_CANARY * 8) + 7(%eax) | ||
| 130 | |||
| 131 | mov $PVH_CANARY_SEL,%eax | ||
| 132 | mov %eax,%gs | ||
| 133 | |||
| 110 | call mk_early_pgtbl_32 | 134 | call mk_early_pgtbl_32 |
| 111 | 135 | ||
| 112 | mov $_pa(initial_page_table), %eax | 136 | mov $_pa(initial_page_table), %eax |
| @@ -116,13 +140,13 @@ ENTRY(pvh_start_xen) | |||
| 116 | or $(X86_CR0_PG | X86_CR0_PE), %eax | 140 | or $(X86_CR0_PG | X86_CR0_PE), %eax |
| 117 | mov %eax, %cr0 | 141 | mov %eax, %cr0 |
| 118 | 142 | ||
| 119 | ljmp $__BOOT_CS, $1f | 143 | ljmp $PVH_CS_SEL, $1f |
| 120 | 1: | 144 | 1: |
| 121 | call xen_prepare_pvh | 145 | call xen_prepare_pvh |
| 122 | mov $_pa(pvh_bootparams), %esi | 146 | mov $_pa(pvh_bootparams), %esi |
| 123 | 147 | ||
| 124 | /* startup_32 doesn't expect paging and PAE to be on. */ | 148 | /* startup_32 doesn't expect paging and PAE to be on. */ |
| 125 | ljmp $__BOOT_CS, $_pa(2f) | 149 | ljmp $PVH_CS_SEL, $_pa(2f) |
| 126 | 2: | 150 | 2: |
| 127 | mov %cr0, %eax | 151 | mov %cr0, %eax |
| 128 | and $~X86_CR0_PG, %eax | 152 | and $~X86_CR0_PG, %eax |
| @@ -131,7 +155,7 @@ ENTRY(pvh_start_xen) | |||
| 131 | and $~X86_CR4_PAE, %eax | 155 | and $~X86_CR4_PAE, %eax |
| 132 | mov %eax, %cr4 | 156 | mov %eax, %cr4 |
| 133 | 157 | ||
| 134 | ljmp $__BOOT_CS, $_pa(startup_32) | 158 | ljmp $PVH_CS_SEL, $_pa(startup_32) |
| 135 | #endif | 159 | #endif |
| 136 | END(pvh_start_xen) | 160 | END(pvh_start_xen) |
| 137 | 161 | ||
| @@ -143,16 +167,19 @@ gdt: | |||
| 143 | .word 0 | 167 | .word 0 |
| 144 | gdt_start: | 168 | gdt_start: |
| 145 | .quad 0x0000000000000000 /* NULL descriptor */ | 169 | .quad 0x0000000000000000 /* NULL descriptor */ |
| 146 | .quad 0x0000000000000000 /* reserved */ | ||
| 147 | #ifdef CONFIG_X86_64 | 170 | #ifdef CONFIG_X86_64 |
| 148 | .quad GDT_ENTRY(0xa09a, 0, 0xfffff) /* __KERNEL_CS */ | 171 | .quad GDT_ENTRY(0xa09a, 0, 0xfffff) /* PVH_CS_SEL */ |
| 149 | #else | 172 | #else |
| 150 | .quad GDT_ENTRY(0xc09a, 0, 0xfffff) /* __KERNEL_CS */ | 173 | .quad GDT_ENTRY(0xc09a, 0, 0xfffff) /* PVH_CS_SEL */ |
| 151 | #endif | 174 | #endif |
| 152 | .quad GDT_ENTRY(0xc092, 0, 0xfffff) /* __KERNEL_DS */ | 175 | .quad GDT_ENTRY(0xc092, 0, 0xfffff) /* PVH_DS_SEL */ |
| 176 | .quad GDT_ENTRY(0x4090, 0, 0x18) /* PVH_CANARY_SEL */ | ||
| 153 | gdt_end: | 177 | gdt_end: |
| 154 | 178 | ||
| 155 | .balign 4 | 179 | .balign 16 |
| 180 | canary: | ||
| 181 | .fill 48, 1, 0 | ||
| 182 | |||
| 156 | early_stack: | 183 | early_stack: |
| 157 | .fill 256, 1, 0 | 184 | .fill 256, 1, 0 |
| 158 | early_stack_end: | 185 | early_stack_end: |
diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c index 4dd0668003e7..679da1abd73c 100644 --- a/drivers/net/xen-netfront.c +++ b/drivers/net/xen-netfront.c | |||
| @@ -564,7 +564,7 @@ static u16 xennet_select_queue(struct net_device *dev, struct sk_buff *skb, | |||
| 564 | 564 | ||
| 565 | #define MAX_XEN_SKB_FRAGS (65536 / XEN_PAGE_SIZE + 1) | 565 | #define MAX_XEN_SKB_FRAGS (65536 / XEN_PAGE_SIZE + 1) |
| 566 | 566 | ||
| 567 | static int xennet_start_xmit(struct sk_buff *skb, struct net_device *dev) | 567 | static netdev_tx_t xennet_start_xmit(struct sk_buff *skb, struct net_device *dev) |
| 568 | { | 568 | { |
| 569 | struct netfront_info *np = netdev_priv(dev); | 569 | struct netfront_info *np = netdev_priv(dev); |
| 570 | struct netfront_stats *tx_stats = this_cpu_ptr(np->tx_stats); | 570 | struct netfront_stats *tx_stats = this_cpu_ptr(np->tx_stats); |
diff --git a/drivers/xen/privcmd.c b/drivers/xen/privcmd.c index 1c909183c42a..8ae0349d9f0a 100644 --- a/drivers/xen/privcmd.c +++ b/drivers/xen/privcmd.c | |||
| @@ -33,6 +33,7 @@ | |||
| 33 | #include <xen/xen.h> | 33 | #include <xen/xen.h> |
| 34 | #include <xen/privcmd.h> | 34 | #include <xen/privcmd.h> |
| 35 | #include <xen/interface/xen.h> | 35 | #include <xen/interface/xen.h> |
| 36 | #include <xen/interface/memory.h> | ||
| 36 | #include <xen/interface/hvm/dm_op.h> | 37 | #include <xen/interface/hvm/dm_op.h> |
| 37 | #include <xen/features.h> | 38 | #include <xen/features.h> |
| 38 | #include <xen/page.h> | 39 | #include <xen/page.h> |
| @@ -722,6 +723,134 @@ static long privcmd_ioctl_restrict(struct file *file, void __user *udata) | |||
| 722 | return 0; | 723 | return 0; |
| 723 | } | 724 | } |
| 724 | 725 | ||
| 726 | struct remap_pfn { | ||
| 727 | struct mm_struct *mm; | ||
| 728 | struct page **pages; | ||
| 729 | pgprot_t prot; | ||
| 730 | unsigned long i; | ||
| 731 | }; | ||
| 732 | |||
| 733 | static int remap_pfn_fn(pte_t *ptep, pgtable_t token, unsigned long addr, | ||
| 734 | void *data) | ||
| 735 | { | ||
| 736 | struct remap_pfn *r = data; | ||
| 737 | struct page *page = r->pages[r->i]; | ||
| 738 | pte_t pte = pte_mkspecial(pfn_pte(page_to_pfn(page), r->prot)); | ||
| 739 | |||
| 740 | set_pte_at(r->mm, addr, ptep, pte); | ||
| 741 | r->i++; | ||
| 742 | |||
| 743 | return 0; | ||
| 744 | } | ||
| 745 | |||
| 746 | static long privcmd_ioctl_mmap_resource(struct file *file, void __user *udata) | ||
| 747 | { | ||
| 748 | struct privcmd_data *data = file->private_data; | ||
| 749 | struct mm_struct *mm = current->mm; | ||
| 750 | struct vm_area_struct *vma; | ||
| 751 | struct privcmd_mmap_resource kdata; | ||
| 752 | xen_pfn_t *pfns = NULL; | ||
| 753 | struct xen_mem_acquire_resource xdata; | ||
| 754 | int rc; | ||
| 755 | |||
| 756 | if (copy_from_user(&kdata, udata, sizeof(kdata))) | ||
| 757 | return -EFAULT; | ||
| 758 | |||
| 759 | /* If restriction is in place, check the domid matches */ | ||
| 760 | if (data->domid != DOMID_INVALID && data->domid != kdata.dom) | ||
| 761 | return -EPERM; | ||
| 762 | |||
| 763 | down_write(&mm->mmap_sem); | ||
| 764 | |||
| 765 | vma = find_vma(mm, kdata.addr); | ||
| 766 | if (!vma || vma->vm_ops != &privcmd_vm_ops) { | ||
| 767 | rc = -EINVAL; | ||
| 768 | goto out; | ||
| 769 | } | ||
| 770 | |||
| 771 | pfns = kcalloc(kdata.num, sizeof(*pfns), GFP_KERNEL); | ||
| 772 | if (!pfns) { | ||
| 773 | rc = -ENOMEM; | ||
| 774 | goto out; | ||
| 775 | } | ||
| 776 | |||
| 777 | if (xen_feature(XENFEAT_auto_translated_physmap)) { | ||
| 778 | unsigned int nr = DIV_ROUND_UP(kdata.num, XEN_PFN_PER_PAGE); | ||
| 779 | struct page **pages; | ||
| 780 | unsigned int i; | ||
| 781 | |||
| 782 | rc = alloc_empty_pages(vma, nr); | ||
| 783 | if (rc < 0) | ||
| 784 | goto out; | ||
| 785 | |||
| 786 | pages = vma->vm_private_data; | ||
| 787 | for (i = 0; i < kdata.num; i++) { | ||
| 788 | xen_pfn_t pfn = | ||
| 789 | page_to_xen_pfn(pages[i / XEN_PFN_PER_PAGE]); | ||
| 790 | |||
| 791 | pfns[i] = pfn + (i % XEN_PFN_PER_PAGE); | ||
| 792 | } | ||
| 793 | } else | ||
| 794 | vma->vm_private_data = PRIV_VMA_LOCKED; | ||
| 795 | |||
| 796 | memset(&xdata, 0, sizeof(xdata)); | ||
| 797 | xdata.domid = kdata.dom; | ||
| 798 | xdata.type = kdata.type; | ||
| 799 | xdata.id = kdata.id; | ||
| 800 | xdata.frame = kdata.idx; | ||
| 801 | xdata.nr_frames = kdata.num; | ||
| 802 | set_xen_guest_handle(xdata.frame_list, pfns); | ||
| 803 | |||
| 804 | xen_preemptible_hcall_begin(); | ||
| 805 | rc = HYPERVISOR_memory_op(XENMEM_acquire_resource, &xdata); | ||
| 806 | xen_preemptible_hcall_end(); | ||
| 807 | |||
| 808 | if (rc) | ||
| 809 | goto out; | ||
| 810 | |||
| 811 | if (xen_feature(XENFEAT_auto_translated_physmap)) { | ||
| 812 | struct remap_pfn r = { | ||
| 813 | .mm = vma->vm_mm, | ||
| 814 | .pages = vma->vm_private_data, | ||
| 815 | .prot = vma->vm_page_prot, | ||
| 816 | }; | ||
| 817 | |||
| 818 | rc = apply_to_page_range(r.mm, kdata.addr, | ||
| 819 | kdata.num << PAGE_SHIFT, | ||
| 820 | remap_pfn_fn, &r); | ||
| 821 | } else { | ||
| 822 | unsigned int domid = | ||
| 823 | (xdata.flags & XENMEM_rsrc_acq_caller_owned) ? | ||
| 824 | DOMID_SELF : kdata.dom; | ||
| 825 | int num; | ||
| 826 | |||
| 827 | num = xen_remap_domain_mfn_array(vma, | ||
| 828 | kdata.addr & PAGE_MASK, | ||
| 829 | pfns, kdata.num, (int *)pfns, | ||
| 830 | vma->vm_page_prot, | ||
| 831 | domid, | ||
| 832 | vma->vm_private_data); | ||
| 833 | if (num < 0) | ||
| 834 | rc = num; | ||
| 835 | else if (num != kdata.num) { | ||
| 836 | unsigned int i; | ||
| 837 | |||
| 838 | for (i = 0; i < num; i++) { | ||
| 839 | rc = pfns[i]; | ||
| 840 | if (rc < 0) | ||
| 841 | break; | ||
| 842 | } | ||
| 843 | } else | ||
| 844 | rc = 0; | ||
| 845 | } | ||
| 846 | |||
| 847 | out: | ||
| 848 | up_write(&mm->mmap_sem); | ||
| 849 | kfree(pfns); | ||
| 850 | |||
| 851 | return rc; | ||
| 852 | } | ||
| 853 | |||
| 725 | static long privcmd_ioctl(struct file *file, | 854 | static long privcmd_ioctl(struct file *file, |
| 726 | unsigned int cmd, unsigned long data) | 855 | unsigned int cmd, unsigned long data) |
| 727 | { | 856 | { |
| @@ -753,6 +882,10 @@ static long privcmd_ioctl(struct file *file, | |||
| 753 | ret = privcmd_ioctl_restrict(file, udata); | 882 | ret = privcmd_ioctl_restrict(file, udata); |
| 754 | break; | 883 | break; |
| 755 | 884 | ||
| 885 | case IOCTL_PRIVCMD_MMAP_RESOURCE: | ||
| 886 | ret = privcmd_ioctl_mmap_resource(file, udata); | ||
| 887 | break; | ||
| 888 | |||
| 756 | default: | 889 | default: |
| 757 | break; | 890 | break; |
| 758 | } | 891 | } |
| @@ -801,7 +934,7 @@ static void privcmd_close(struct vm_area_struct *vma) | |||
| 801 | kfree(pages); | 934 | kfree(pages); |
| 802 | } | 935 | } |
| 803 | 936 | ||
| 804 | static int privcmd_fault(struct vm_fault *vmf) | 937 | static vm_fault_t privcmd_fault(struct vm_fault *vmf) |
| 805 | { | 938 | { |
| 806 | printk(KERN_DEBUG "privcmd_fault: vma=%p %lx-%lx, pgoff=%lx, uv=%p\n", | 939 | printk(KERN_DEBUG "privcmd_fault: vma=%p %lx-%lx, pgoff=%lx, uv=%p\n", |
| 807 | vmf->vma, vmf->vma->vm_start, vmf->vma->vm_end, | 940 | vmf->vma, vmf->vma->vm_start, vmf->vma->vm_end, |
diff --git a/drivers/xen/xenbus/xenbus_probe.c b/drivers/xen/xenbus/xenbus_probe.c index ec9eb4fba59c..f2088838f690 100644 --- a/drivers/xen/xenbus/xenbus_probe.c +++ b/drivers/xen/xenbus/xenbus_probe.c | |||
| @@ -710,7 +710,7 @@ static int __init xenstored_local_init(void) | |||
| 710 | if (!page) | 710 | if (!page) |
| 711 | goto out_err; | 711 | goto out_err; |
| 712 | 712 | ||
| 713 | xen_store_gfn = xen_start_info->store_mfn = virt_to_gfn((void *)page); | 713 | xen_store_gfn = virt_to_gfn((void *)page); |
| 714 | 714 | ||
| 715 | /* Next allocate a local port which xenstored can bind to */ | 715 | /* Next allocate a local port which xenstored can bind to */ |
| 716 | alloc_unbound.dom = DOMID_SELF; | 716 | alloc_unbound.dom = DOMID_SELF; |
| @@ -722,8 +722,7 @@ static int __init xenstored_local_init(void) | |||
| 722 | goto out_err; | 722 | goto out_err; |
| 723 | 723 | ||
| 724 | BUG_ON(err); | 724 | BUG_ON(err); |
| 725 | xen_store_evtchn = xen_start_info->store_evtchn = | 725 | xen_store_evtchn = alloc_unbound.port; |
| 726 | alloc_unbound.port; | ||
| 727 | 726 | ||
| 728 | return 0; | 727 | return 0; |
| 729 | 728 | ||
diff --git a/include/uapi/xen/privcmd.h b/include/uapi/xen/privcmd.h index 39d3e7b8e993..d2029556083e 100644 --- a/include/uapi/xen/privcmd.h +++ b/include/uapi/xen/privcmd.h | |||
| @@ -89,6 +89,15 @@ struct privcmd_dm_op { | |||
| 89 | const struct privcmd_dm_op_buf __user *ubufs; | 89 | const struct privcmd_dm_op_buf __user *ubufs; |
| 90 | }; | 90 | }; |
| 91 | 91 | ||
| 92 | struct privcmd_mmap_resource { | ||
| 93 | domid_t dom; | ||
| 94 | __u32 type; | ||
| 95 | __u32 id; | ||
| 96 | __u32 idx; | ||
| 97 | __u64 num; | ||
| 98 | __u64 addr; | ||
| 99 | }; | ||
| 100 | |||
| 92 | /* | 101 | /* |
| 93 | * @cmd: IOCTL_PRIVCMD_HYPERCALL | 102 | * @cmd: IOCTL_PRIVCMD_HYPERCALL |
| 94 | * @arg: &privcmd_hypercall_t | 103 | * @arg: &privcmd_hypercall_t |
| @@ -114,5 +123,7 @@ struct privcmd_dm_op { | |||
| 114 | _IOC(_IOC_NONE, 'P', 5, sizeof(struct privcmd_dm_op)) | 123 | _IOC(_IOC_NONE, 'P', 5, sizeof(struct privcmd_dm_op)) |
| 115 | #define IOCTL_PRIVCMD_RESTRICT \ | 124 | #define IOCTL_PRIVCMD_RESTRICT \ |
| 116 | _IOC(_IOC_NONE, 'P', 6, sizeof(domid_t)) | 125 | _IOC(_IOC_NONE, 'P', 6, sizeof(domid_t)) |
| 126 | #define IOCTL_PRIVCMD_MMAP_RESOURCE \ | ||
| 127 | _IOC(_IOC_NONE, 'P', 7, sizeof(struct privcmd_mmap_resource)) | ||
| 117 | 128 | ||
| 118 | #endif /* __LINUX_PUBLIC_PRIVCMD_H__ */ | 129 | #endif /* __LINUX_PUBLIC_PRIVCMD_H__ */ |
diff --git a/include/xen/interface/memory.h b/include/xen/interface/memory.h index 583dd93b3016..4c5751c26f87 100644 --- a/include/xen/interface/memory.h +++ b/include/xen/interface/memory.h | |||
| @@ -265,4 +265,70 @@ struct xen_remove_from_physmap { | |||
| 265 | }; | 265 | }; |
| 266 | DEFINE_GUEST_HANDLE_STRUCT(xen_remove_from_physmap); | 266 | DEFINE_GUEST_HANDLE_STRUCT(xen_remove_from_physmap); |
| 267 | 267 | ||
| 268 | /* | ||
| 269 | * Get the pages for a particular guest resource, so that they can be | ||
| 270 | * mapped directly by a tools domain. | ||
| 271 | */ | ||
| 272 | #define XENMEM_acquire_resource 28 | ||
| 273 | struct xen_mem_acquire_resource { | ||
| 274 | /* IN - The domain whose resource is to be mapped */ | ||
| 275 | domid_t domid; | ||
| 276 | /* IN - the type of resource */ | ||
| 277 | uint16_t type; | ||
| 278 | |||
| 279 | #define XENMEM_resource_ioreq_server 0 | ||
| 280 | #define XENMEM_resource_grant_table 1 | ||
| 281 | |||
| 282 | /* | ||
| 283 | * IN - a type-specific resource identifier, which must be zero | ||
| 284 | * unless stated otherwise. | ||
| 285 | * | ||
| 286 | * type == XENMEM_resource_ioreq_server -> id == ioreq server id | ||
| 287 | * type == XENMEM_resource_grant_table -> id defined below | ||
| 288 | */ | ||
| 289 | uint32_t id; | ||
| 290 | |||
| 291 | #define XENMEM_resource_grant_table_id_shared 0 | ||
| 292 | #define XENMEM_resource_grant_table_id_status 1 | ||
| 293 | |||
| 294 | /* IN/OUT - As an IN parameter number of frames of the resource | ||
| 295 | * to be mapped. However, if the specified value is 0 and | ||
| 296 | * frame_list is NULL then this field will be set to the | ||
| 297 | * maximum value supported by the implementation on return. | ||
| 298 | */ | ||
| 299 | uint32_t nr_frames; | ||
| 300 | /* | ||
| 301 | * OUT - Must be zero on entry. On return this may contain a bitwise | ||
| 302 | * OR of the following values. | ||
| 303 | */ | ||
| 304 | uint32_t flags; | ||
| 305 | |||
| 306 | /* The resource pages have been assigned to the calling domain */ | ||
| 307 | #define _XENMEM_rsrc_acq_caller_owned 0 | ||
| 308 | #define XENMEM_rsrc_acq_caller_owned (1u << _XENMEM_rsrc_acq_caller_owned) | ||
| 309 | |||
| 310 | /* | ||
| 311 | * IN - the index of the initial frame to be mapped. This parameter | ||
| 312 | * is ignored if nr_frames is 0. | ||
| 313 | */ | ||
| 314 | uint64_t frame; | ||
| 315 | |||
| 316 | #define XENMEM_resource_ioreq_server_frame_bufioreq 0 | ||
| 317 | #define XENMEM_resource_ioreq_server_frame_ioreq(n) (1 + (n)) | ||
| 318 | |||
| 319 | /* | ||
| 320 | * IN/OUT - If the tools domain is PV then, upon return, frame_list | ||
| 321 | * will be populated with the MFNs of the resource. | ||
| 322 | * If the tools domain is HVM then it is expected that, on | ||
| 323 | * entry, frame_list will be populated with a list of GFNs | ||
| 324 | * that will be mapped to the MFNs of the resource. | ||
| 325 | * If -EIO is returned then the frame_list has only been | ||
| 326 | * partially mapped and it is up to the caller to unmap all | ||
| 327 | * the GFNs. | ||
| 328 | * This parameter may be NULL if nr_frames is 0. | ||
| 329 | */ | ||
| 330 | GUEST_HANDLE(xen_pfn_t) frame_list; | ||
| 331 | }; | ||
| 332 | DEFINE_GUEST_HANDLE_STRUCT(xen_mem_acquire_resource); | ||
| 333 | |||
| 268 | #endif /* __XEN_PUBLIC_MEMORY_H__ */ | 334 | #endif /* __XEN_PUBLIC_MEMORY_H__ */ |
diff --git a/include/xen/interface/xen.h b/include/xen/interface/xen.h index 4f4830ef8f93..8bfb242f433e 100644 --- a/include/xen/interface/xen.h +++ b/include/xen/interface/xen.h | |||
| @@ -265,9 +265,10 @@ | |||
| 265 | * | 265 | * |
| 266 | * PAT (bit 7 on) --> PWT (bit 3 on) and clear bit 7. | 266 | * PAT (bit 7 on) --> PWT (bit 3 on) and clear bit 7. |
| 267 | */ | 267 | */ |
| 268 | #define MMU_NORMAL_PT_UPDATE 0 /* checked '*ptr = val'. ptr is MA. */ | 268 | #define MMU_NORMAL_PT_UPDATE 0 /* checked '*ptr = val'. ptr is MA. */ |
| 269 | #define MMU_MACHPHYS_UPDATE 1 /* ptr = MA of frame to modify entry for */ | 269 | #define MMU_MACHPHYS_UPDATE 1 /* ptr = MA of frame to modify entry for */ |
| 270 | #define MMU_PT_UPDATE_PRESERVE_AD 2 /* atomically: *ptr = val | (*ptr&(A|D)) */ | 270 | #define MMU_PT_UPDATE_PRESERVE_AD 2 /* atomically: *ptr = val | (*ptr&(A|D)) */ |
| 271 | #define MMU_PT_UPDATE_NO_TRANSLATE 3 /* checked '*ptr = val'. ptr is MA. */ | ||
| 271 | 272 | ||
| 272 | /* | 273 | /* |
| 273 | * MMU EXTENDED OPERATIONS | 274 | * MMU EXTENDED OPERATIONS |
diff --git a/include/xen/xen-ops.h b/include/xen/xen-ops.h index fd23e42c6024..fd18c974a619 100644 --- a/include/xen/xen-ops.h +++ b/include/xen/xen-ops.h | |||
| @@ -63,7 +63,7 @@ static inline void xen_destroy_contiguous_region(phys_addr_t pstart, | |||
| 63 | struct vm_area_struct; | 63 | struct vm_area_struct; |
| 64 | 64 | ||
| 65 | /* | 65 | /* |
| 66 | * xen_remap_domain_gfn_array() - map an array of foreign frames | 66 | * xen_remap_domain_gfn_array() - map an array of foreign frames by gfn |
| 67 | * @vma: VMA to map the pages into | 67 | * @vma: VMA to map the pages into |
| 68 | * @addr: Address at which to map the pages | 68 | * @addr: Address at which to map the pages |
| 69 | * @gfn: Array of GFNs to map | 69 | * @gfn: Array of GFNs to map |
| @@ -86,6 +86,28 @@ int xen_remap_domain_gfn_array(struct vm_area_struct *vma, | |||
| 86 | unsigned domid, | 86 | unsigned domid, |
| 87 | struct page **pages); | 87 | struct page **pages); |
| 88 | 88 | ||
| 89 | /* | ||
| 90 | * xen_remap_domain_mfn_array() - map an array of foreign frames by mfn | ||
| 91 | * @vma: VMA to map the pages into | ||
| 92 | * @addr: Address at which to map the pages | ||
| 93 | * @mfn: Array of MFNs to map | ||
| 94 | * @nr: Number entries in the MFN array | ||
| 95 | * @err_ptr: Returns per-MFN error status. | ||
| 96 | * @prot: page protection mask | ||
| 97 | * @domid: Domain owning the pages | ||
| 98 | * @pages: Array of pages if this domain has an auto-translated physmap | ||
| 99 | * | ||
| 100 | * @mfn and @err_ptr may point to the same buffer, the MFNs will be | ||
| 101 | * overwritten by the error codes after they are mapped. | ||
| 102 | * | ||
| 103 | * Returns the number of successfully mapped frames, or a -ve error | ||
| 104 | * code. | ||
| 105 | */ | ||
| 106 | int xen_remap_domain_mfn_array(struct vm_area_struct *vma, | ||
| 107 | unsigned long addr, xen_pfn_t *mfn, int nr, | ||
| 108 | int *err_ptr, pgprot_t prot, | ||
| 109 | unsigned int domid, struct page **pages); | ||
| 110 | |||
| 89 | /* xen_remap_domain_gfn_range() - map a range of foreign frames | 111 | /* xen_remap_domain_gfn_range() - map a range of foreign frames |
| 90 | * @vma: VMA to map the pages into | 112 | * @vma: VMA to map the pages into |
| 91 | * @addr: Address at which to map the pages | 113 | * @addr: Address at which to map the pages |
