diff options
| -rw-r--r-- | arch/arm/include/asm/xen/interface.h | 1 | ||||
| -rw-r--r-- | arch/arm/xen/enlighten.c | 100 | ||||
| -rw-r--r-- | arch/x86/include/asm/xen/interface.h | 1 | ||||
| -rw-r--r-- | include/xen/interface/memory.h | 44 |
4 files changed, 141 insertions, 5 deletions
diff --git a/arch/arm/include/asm/xen/interface.h b/arch/arm/include/asm/xen/interface.h index 5000397134b4..1151188bcd83 100644 --- a/arch/arm/include/asm/xen/interface.h +++ b/arch/arm/include/asm/xen/interface.h | |||
| @@ -49,6 +49,7 @@ DEFINE_GUEST_HANDLE(void); | |||
| 49 | DEFINE_GUEST_HANDLE(uint64_t); | 49 | DEFINE_GUEST_HANDLE(uint64_t); |
| 50 | DEFINE_GUEST_HANDLE(uint32_t); | 50 | DEFINE_GUEST_HANDLE(uint32_t); |
| 51 | DEFINE_GUEST_HANDLE(xen_pfn_t); | 51 | DEFINE_GUEST_HANDLE(xen_pfn_t); |
| 52 | DEFINE_GUEST_HANDLE(xen_ulong_t); | ||
| 52 | 53 | ||
| 53 | /* Maximum number of virtual CPUs in multi-processor guests. */ | 54 | /* Maximum number of virtual CPUs in multi-processor guests. */ |
| 54 | #define MAX_VIRT_CPUS 1 | 55 | #define MAX_VIRT_CPUS 1 |
diff --git a/arch/arm/xen/enlighten.c b/arch/arm/xen/enlighten.c index ba5cc134a7d3..f28fc1ac8760 100644 --- a/arch/arm/xen/enlighten.c +++ b/arch/arm/xen/enlighten.c | |||
| @@ -9,6 +9,7 @@ | |||
| 9 | #include <xen/platform_pci.h> | 9 | #include <xen/platform_pci.h> |
| 10 | #include <xen/xenbus.h> | 10 | #include <xen/xenbus.h> |
| 11 | #include <xen/page.h> | 11 | #include <xen/page.h> |
| 12 | #include <xen/xen-ops.h> | ||
| 12 | #include <asm/xen/hypervisor.h> | 13 | #include <asm/xen/hypervisor.h> |
| 13 | #include <asm/xen/hypercall.h> | 14 | #include <asm/xen/hypercall.h> |
| 14 | #include <linux/interrupt.h> | 15 | #include <linux/interrupt.h> |
| @@ -18,6 +19,8 @@ | |||
| 18 | #include <linux/of_irq.h> | 19 | #include <linux/of_irq.h> |
| 19 | #include <linux/of_address.h> | 20 | #include <linux/of_address.h> |
| 20 | 21 | ||
| 22 | #include <linux/mm.h> | ||
| 23 | |||
| 21 | struct start_info _xen_start_info; | 24 | struct start_info _xen_start_info; |
| 22 | struct start_info *xen_start_info = &_xen_start_info; | 25 | struct start_info *xen_start_info = &_xen_start_info; |
| 23 | EXPORT_SYMBOL_GPL(xen_start_info); | 26 | EXPORT_SYMBOL_GPL(xen_start_info); |
| @@ -43,15 +46,106 @@ EXPORT_SYMBOL_GPL(xen_platform_pci_unplug); | |||
| 43 | 46 | ||
| 44 | static __read_mostly int xen_events_irq = -1; | 47 | static __read_mostly int xen_events_irq = -1; |
| 45 | 48 | ||
| 49 | /* map fgmfn of domid to lpfn in the current domain */ | ||
| 50 | static int map_foreign_page(unsigned long lpfn, unsigned long fgmfn, | ||
| 51 | unsigned int domid) | ||
| 52 | { | ||
| 53 | int rc; | ||
| 54 | struct xen_add_to_physmap_range xatp = { | ||
| 55 | .domid = DOMID_SELF, | ||
| 56 | .foreign_domid = domid, | ||
| 57 | .size = 1, | ||
| 58 | .space = XENMAPSPACE_gmfn_foreign, | ||
| 59 | }; | ||
| 60 | xen_ulong_t idx = fgmfn; | ||
| 61 | xen_pfn_t gpfn = lpfn; | ||
| 62 | |||
| 63 | set_xen_guest_handle(xatp.idxs, &idx); | ||
| 64 | set_xen_guest_handle(xatp.gpfns, &gpfn); | ||
| 65 | |||
| 66 | rc = HYPERVISOR_memory_op(XENMEM_add_to_physmap_range, &xatp); | ||
| 67 | if (rc) { | ||
| 68 | pr_warn("Failed to map pfn to mfn rc:%d pfn:%lx mfn:%lx\n", | ||
| 69 | rc, lpfn, fgmfn); | ||
| 70 | return 1; | ||
| 71 | } | ||
| 72 | return 0; | ||
| 73 | } | ||
| 74 | |||
| 75 | struct remap_data { | ||
| 76 | xen_pfn_t fgmfn; /* foreign domain's gmfn */ | ||
| 77 | pgprot_t prot; | ||
| 78 | domid_t domid; | ||
| 79 | struct vm_area_struct *vma; | ||
| 80 | int index; | ||
| 81 | struct page **pages; | ||
| 82 | struct xen_remap_mfn_info *info; | ||
| 83 | }; | ||
| 84 | |||
| 85 | static int remap_pte_fn(pte_t *ptep, pgtable_t token, unsigned long addr, | ||
| 86 | void *data) | ||
| 87 | { | ||
| 88 | struct remap_data *info = data; | ||
| 89 | struct page *page = info->pages[info->index++]; | ||
| 90 | unsigned long pfn = page_to_pfn(page); | ||
| 91 | pte_t pte = pfn_pte(pfn, info->prot); | ||
| 92 | |||
| 93 | if (map_foreign_page(pfn, info->fgmfn, info->domid)) | ||
| 94 | return -EFAULT; | ||
| 95 | set_pte_at(info->vma->vm_mm, addr, ptep, pte); | ||
| 96 | |||
| 97 | return 0; | ||
| 98 | } | ||
| 99 | |||
| 46 | int xen_remap_domain_mfn_range(struct vm_area_struct *vma, | 100 | int xen_remap_domain_mfn_range(struct vm_area_struct *vma, |
| 47 | unsigned long addr, | 101 | unsigned long addr, |
| 48 | unsigned long mfn, int nr, | 102 | xen_pfn_t mfn, int nr, |
| 49 | pgprot_t prot, unsigned domid) | 103 | pgprot_t prot, unsigned domid, |
| 104 | struct page **pages) | ||
| 50 | { | 105 | { |
| 51 | return -ENOSYS; | 106 | int err; |
| 107 | struct remap_data data; | ||
| 108 | |||
| 109 | /* TBD: Batching, current sole caller only does page at a time */ | ||
| 110 | if (nr > 1) | ||
| 111 | return -EINVAL; | ||
| 112 | |||
| 113 | data.fgmfn = mfn; | ||
| 114 | data.prot = prot; | ||
| 115 | data.domid = domid; | ||
| 116 | data.vma = vma; | ||
| 117 | data.index = 0; | ||
| 118 | data.pages = pages; | ||
| 119 | err = apply_to_page_range(vma->vm_mm, addr, nr << PAGE_SHIFT, | ||
| 120 | remap_pte_fn, &data); | ||
| 121 | return err; | ||
| 52 | } | 122 | } |
| 53 | EXPORT_SYMBOL_GPL(xen_remap_domain_mfn_range); | 123 | EXPORT_SYMBOL_GPL(xen_remap_domain_mfn_range); |
| 54 | 124 | ||
| 125 | int xen_unmap_domain_mfn_range(struct vm_area_struct *vma, | ||
| 126 | int nr, struct page **pages) | ||
| 127 | { | ||
| 128 | int i; | ||
| 129 | |||
| 130 | for (i = 0; i < nr; i++) { | ||
| 131 | struct xen_remove_from_physmap xrp; | ||
| 132 | unsigned long rc, pfn; | ||
| 133 | |||
| 134 | pfn = page_to_pfn(pages[i]); | ||
| 135 | |||
| 136 | xrp.domid = DOMID_SELF; | ||
| 137 | xrp.gpfn = pfn; | ||
| 138 | rc = HYPERVISOR_memory_op(XENMEM_remove_from_physmap, &xrp); | ||
| 139 | if (rc) { | ||
| 140 | pr_warn("Failed to unmap pfn:%lx rc:%ld\n", | ||
| 141 | pfn, rc); | ||
| 142 | return rc; | ||
| 143 | } | ||
| 144 | } | ||
| 145 | return 0; | ||
| 146 | } | ||
| 147 | EXPORT_SYMBOL_GPL(xen_unmap_domain_mfn_range); | ||
| 148 | |||
| 55 | /* | 149 | /* |
| 56 | * see Documentation/devicetree/bindings/arm/xen.txt for the | 150 | * see Documentation/devicetree/bindings/arm/xen.txt for the |
| 57 | * documentation of the Xen Device Tree format. | 151 | * documentation of the Xen Device Tree format. |
diff --git a/arch/x86/include/asm/xen/interface.h b/arch/x86/include/asm/xen/interface.h index 54d52ff1304a..fd9cb7695b5f 100644 --- a/arch/x86/include/asm/xen/interface.h +++ b/arch/x86/include/asm/xen/interface.h | |||
| @@ -63,6 +63,7 @@ DEFINE_GUEST_HANDLE(void); | |||
| 63 | DEFINE_GUEST_HANDLE(uint64_t); | 63 | DEFINE_GUEST_HANDLE(uint64_t); |
| 64 | DEFINE_GUEST_HANDLE(uint32_t); | 64 | DEFINE_GUEST_HANDLE(uint32_t); |
| 65 | DEFINE_GUEST_HANDLE(xen_pfn_t); | 65 | DEFINE_GUEST_HANDLE(xen_pfn_t); |
| 66 | DEFINE_GUEST_HANDLE(xen_ulong_t); | ||
| 66 | #endif | 67 | #endif |
| 67 | 68 | ||
| 68 | #ifndef HYPERVISOR_VIRT_START | 69 | #ifndef HYPERVISOR_VIRT_START |
diff --git a/include/xen/interface/memory.h b/include/xen/interface/memory.h index 90712e2072d5..b40a4315cb8b 100644 --- a/include/xen/interface/memory.h +++ b/include/xen/interface/memory.h | |||
| @@ -153,6 +153,14 @@ struct xen_machphys_mapping { | |||
| 153 | }; | 153 | }; |
| 154 | DEFINE_GUEST_HANDLE_STRUCT(xen_machphys_mapping_t); | 154 | DEFINE_GUEST_HANDLE_STRUCT(xen_machphys_mapping_t); |
| 155 | 155 | ||
| 156 | #define XENMAPSPACE_shared_info 0 /* shared info page */ | ||
| 157 | #define XENMAPSPACE_grant_table 1 /* grant table page */ | ||
| 158 | #define XENMAPSPACE_gmfn 2 /* GMFN */ | ||
| 159 | #define XENMAPSPACE_gmfn_range 3 /* GMFN range, XENMEM_add_to_physmap only. */ | ||
| 160 | #define XENMAPSPACE_gmfn_foreign 4 /* GMFN from another dom, | ||
| 161 | * XENMEM_add_to_physmap_range only. | ||
| 162 | */ | ||
| 163 | |||
| 156 | /* | 164 | /* |
| 157 | * Sets the GPFN at which a particular page appears in the specified guest's | 165 | * Sets the GPFN at which a particular page appears in the specified guest's |
| 158 | * pseudophysical address space. | 166 | * pseudophysical address space. |
| @@ -167,8 +175,6 @@ struct xen_add_to_physmap { | |||
| 167 | uint16_t size; | 175 | uint16_t size; |
| 168 | 176 | ||
| 169 | /* Source mapping space. */ | 177 | /* Source mapping space. */ |
| 170 | #define XENMAPSPACE_shared_info 0 /* shared info page */ | ||
| 171 | #define XENMAPSPACE_grant_table 1 /* grant table page */ | ||
| 172 | unsigned int space; | 178 | unsigned int space; |
| 173 | 179 | ||
| 174 | /* Index into source mapping space. */ | 180 | /* Index into source mapping space. */ |
| @@ -182,6 +188,24 @@ DEFINE_GUEST_HANDLE_STRUCT(xen_add_to_physmap); | |||
| 182 | /*** REMOVED ***/ | 188 | /*** REMOVED ***/ |
| 183 | /*#define XENMEM_translate_gpfn_list 8*/ | 189 | /*#define XENMEM_translate_gpfn_list 8*/ |
| 184 | 190 | ||
| 191 | #define XENMEM_add_to_physmap_range 23 | ||
| 192 | struct xen_add_to_physmap_range { | ||
| 193 | /* Which domain to change the mapping for. */ | ||
| 194 | domid_t domid; | ||
| 195 | uint16_t space; /* => enum phys_map_space */ | ||
| 196 | |||
| 197 | /* Number of pages to go through */ | ||
| 198 | uint16_t size; | ||
| 199 | domid_t foreign_domid; /* IFF gmfn_foreign */ | ||
| 200 | |||
| 201 | /* Indexes into space being mapped. */ | ||
| 202 | GUEST_HANDLE(xen_ulong_t) idxs; | ||
| 203 | |||
| 204 | /* GPFN in domid where the source mapping page should appear. */ | ||
| 205 | GUEST_HANDLE(xen_pfn_t) gpfns; | ||
| 206 | }; | ||
| 207 | DEFINE_GUEST_HANDLE_STRUCT(xen_add_to_physmap_range); | ||
| 208 | |||
| 185 | /* | 209 | /* |
| 186 | * Returns the pseudo-physical memory map as it was when the domain | 210 | * Returns the pseudo-physical memory map as it was when the domain |
| 187 | * was started (specified by XENMEM_set_memory_map). | 211 | * was started (specified by XENMEM_set_memory_map). |
| @@ -217,4 +241,20 @@ DEFINE_GUEST_HANDLE_STRUCT(xen_memory_map); | |||
| 217 | * during a driver critical region. | 241 | * during a driver critical region. |
| 218 | */ | 242 | */ |
| 219 | extern spinlock_t xen_reservation_lock; | 243 | extern spinlock_t xen_reservation_lock; |
| 244 | |||
| 245 | /* | ||
| 246 | * Unmaps the page appearing at a particular GPFN from the specified guest's | ||
| 247 | * pseudophysical address space. | ||
| 248 | * arg == addr of xen_remove_from_physmap_t. | ||
| 249 | */ | ||
| 250 | #define XENMEM_remove_from_physmap 15 | ||
| 251 | struct xen_remove_from_physmap { | ||
| 252 | /* Which domain to change the mapping for. */ | ||
| 253 | domid_t domid; | ||
| 254 | |||
| 255 | /* GPFN of the current mapping of the page. */ | ||
| 256 | xen_pfn_t gpfn; | ||
| 257 | }; | ||
| 258 | DEFINE_GUEST_HANDLE_STRUCT(xen_remove_from_physmap); | ||
| 259 | |||
| 220 | #endif /* __XEN_PUBLIC_MEMORY_H__ */ | 260 | #endif /* __XEN_PUBLIC_MEMORY_H__ */ |
