aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/xen/enlighten.c11
-rw-r--r--arch/x86/xen/mmu.c60
-rw-r--r--arch/x86/xen/xen-pvh.S47
-rw-r--r--drivers/net/xen-netfront.c2
-rw-r--r--drivers/xen/privcmd.c135
-rw-r--r--drivers/xen/xenbus/xenbus_probe.c5
-rw-r--r--include/uapi/xen/privcmd.h11
-rw-r--r--include/xen/interface/memory.h66
-rw-r--r--include/xen/interface/xen.h7
-rw-r--r--include/xen/xen-ops.h24
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}
90EXPORT_SYMBOL_GPL(xen_unmap_domain_gfn_range); 90EXPORT_SYMBOL_GPL(xen_unmap_domain_gfn_range);
91 91
92/* Not used by XENFEAT_auto_translated guests. */
93int 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}
101EXPORT_SYMBOL_GPL(xen_remap_domain_mfn_array);
102
92static void xen_read_wallclock(struct timespec64 *ts) 103static 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
65struct remap_data { 65struct 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
72static int remap_area_mfn_pte_fn(pte_t *ptep, pgtable_t token, 73static 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
92static int do_remap_gfn(struct vm_area_struct *vma, 98static 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}
178EXPORT_SYMBOL_GPL(xen_remap_domain_gfn_range); 189EXPORT_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}
197EXPORT_SYMBOL_GPL(xen_remap_domain_gfn_array); 209EXPORT_SYMBOL_GPL(xen_remap_domain_gfn_array);
198 210
211int 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}
223EXPORT_SYMBOL_GPL(xen_remap_domain_mfn_array);
224
199/* Returns: 0 success */ 225/* Returns: 0 success */
200int xen_unmap_domain_gfn_range(struct vm_area_struct *vma, 226int 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
57ENTRY(pvh_start_xen) 64ENTRY(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
1001: 1071:
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
1201: 1441:
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)
1262: 1502:
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
136END(pvh_start_xen) 160END(pvh_start_xen)
137 161
@@ -143,16 +167,19 @@ gdt:
143 .word 0 167 .word 0
144gdt_start: 168gdt_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 */
153gdt_end: 177gdt_end:
154 178
155 .balign 4 179 .balign 16
180canary:
181 .fill 48, 1, 0
182
156early_stack: 183early_stack:
157 .fill 256, 1, 0 184 .fill 256, 1, 0
158early_stack_end: 185early_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
567static int xennet_start_xmit(struct sk_buff *skb, struct net_device *dev) 567static 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
726struct remap_pfn {
727 struct mm_struct *mm;
728 struct page **pages;
729 pgprot_t prot;
730 unsigned long i;
731};
732
733static 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
746static 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
847out:
848 up_write(&mm->mmap_sem);
849 kfree(pfns);
850
851 return rc;
852}
853
725static long privcmd_ioctl(struct file *file, 854static 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
804static int privcmd_fault(struct vm_fault *vmf) 937static 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
92struct 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};
266DEFINE_GUEST_HANDLE_STRUCT(xen_remove_from_physmap); 266DEFINE_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
273struct 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};
332DEFINE_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,
63struct vm_area_struct; 63struct 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 */
106int 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