blob: 8b5db51be4dd5b0cecb164336412d356a75498be [file] [log] [blame]
Jeremy Fitzhardingeb5eafe92010-12-06 16:29:22 -08001/*
2 * Xen leaves the responsibility for maintaining p2m mappings to the
3 * guests themselves, but it must also access and update the p2m array
4 * during suspend/resume when all the pages are reallocated.
5 *
Juergen Gross054954e2014-11-28 11:53:58 +01006 * The logical flat p2m table is mapped to a linear kernel memory area.
7 * For accesses by Xen a three-level tree linked via mfns only is set up to
8 * allow the address space to be sparse.
Jeremy Fitzhardingeb5eafe92010-12-06 16:29:22 -08009 *
Juergen Gross054954e2014-11-28 11:53:58 +010010 * Xen
11 * |
12 * p2m_top_mfn
13 * / \
14 * p2m_mid_mfn p2m_mid_mfn
15 * / /
16 * p2m p2m p2m ...
Jeremy Fitzhardingeb5eafe92010-12-06 16:29:22 -080017 *
18 * The p2m_mid_mfn pages are mapped by p2m_top_mfn_p.
19 *
Juergen Gross054954e2014-11-28 11:53:58 +010020 * The p2m_top_mfn level is limited to 1 page, so the maximum representable
21 * pseudo-physical address space is:
Jeremy Fitzhardingeb5eafe92010-12-06 16:29:22 -080022 * P2M_TOP_PER_PAGE * P2M_MID_PER_PAGE * P2M_PER_PAGE pages
23 *
24 * P2M_PER_PAGE depends on the architecture, as a mfn is always
25 * unsigned long (8 bytes on 64-bit, 4 bytes on 32), leading to
Konrad Rzeszutek Wilka3118be2012-06-28 22:12:36 -040026 * 512 and 1024 entries respectively.
Konrad Rzeszutek Wilkf4cec352011-01-18 20:15:21 -050027 *
28 * In short, these structures contain the Machine Frame Number (MFN) of the PFN.
29 *
30 * However not all entries are filled with MFNs. Specifically for all other
31 * leaf entries, or for the top root, or middle one, for which there is a void
32 * entry, we assume it is "missing". So (for example)
33 * pfn_to_mfn(0x90909090)=INVALID_P2M_ENTRY.
Juergen Gross054954e2014-11-28 11:53:58 +010034 * We have a dedicated page p2m_missing with all entries being
35 * INVALID_P2M_ENTRY. This page may be referenced multiple times in the p2m
36 * list/tree in case there are multiple areas with P2M_PER_PAGE invalid pfns.
Konrad Rzeszutek Wilkf4cec352011-01-18 20:15:21 -050037 *
38 * We also have the possibility of setting 1-1 mappings on certain regions, so
39 * that:
40 * pfn_to_mfn(0xc0000)=0xc0000
41 *
42 * The benefit of this is, that we can assume for non-RAM regions (think
David Vrabel3cb83e42014-01-07 11:44:32 +000043 * PCI BARs, or ACPI spaces), we can create mappings easily because we
Konrad Rzeszutek Wilkf4cec352011-01-18 20:15:21 -050044 * get the PFN value to match the MFN.
45 *
Juergen Gross054954e2014-11-28 11:53:58 +010046 * For this to work efficiently we have one new page p2m_identity. All entries
47 * in p2m_identity are set to INVALID_P2M_ENTRY type (Xen toolstack only
48 * recognizes that and MFNs, no other fancy value).
Konrad Rzeszutek Wilkf4cec352011-01-18 20:15:21 -050049 *
50 * On lookup we spot that the entry points to p2m_identity and return the
51 * identity value instead of dereferencing and returning INVALID_P2M_ENTRY.
52 * If the entry points to an allocated page, we just proceed as before and
Juergen Gross054954e2014-11-28 11:53:58 +010053 * return the PFN. If the PFN has IDENTITY_FRAME_BIT set we unmask that in
Konrad Rzeszutek Wilkf4cec352011-01-18 20:15:21 -050054 * appropriate functions (pfn_to_mfn).
55 *
56 * The reason for having the IDENTITY_FRAME_BIT instead of just returning the
57 * PFN is that we could find ourselves where pfn_to_mfn(pfn)==pfn for a
58 * non-identity pfn. To protect ourselves against we elect to set (and get) the
59 * IDENTITY_FRAME_BIT on all identity mapped PFNs.
Jeremy Fitzhardingeb5eafe92010-12-06 16:29:22 -080060 */
61
62#include <linux/init.h>
63#include <linux/module.h>
Jeremy Fitzhardinge448f28312010-12-15 13:19:33 +000064#include <linux/list.h>
65#include <linux/hash.h>
Jeremy Fitzhardinge87f1d402010-12-13 14:42:30 +000066#include <linux/sched.h>
Konrad Rzeszutek Wilk2222e712010-12-22 08:57:30 -050067#include <linux/seq_file.h>
Juergen Gross2c185682014-10-14 13:33:46 +020068#include <linux/bootmem.h>
Juergen Gross7108c9c2014-11-28 11:53:52 +010069#include <linux/slab.h>
Jeremy Fitzhardingeb5eafe92010-12-06 16:29:22 -080070
71#include <asm/cache.h>
72#include <asm/setup.h>
Juergen Gross2e917172014-11-28 11:53:59 +010073#include <asm/uaccess.h>
Jeremy Fitzhardingeb5eafe92010-12-06 16:29:22 -080074
75#include <asm/xen/page.h>
76#include <asm/xen/hypercall.h>
77#include <asm/xen/hypervisor.h>
Stefano Stabelliniee072642013-07-23 17:23:54 +000078#include <xen/balloon.h>
Stefano Stabellini0930bba2011-09-29 11:57:56 +010079#include <xen/grant_table.h>
Jeremy Fitzhardingeb5eafe92010-12-06 16:29:22 -080080
Matt Rushton4fbb67e32014-08-11 11:57:57 -070081#include "p2m.h"
Stefano Stabellini0930bba2011-09-29 11:57:56 +010082#include "multicalls.h"
Jeremy Fitzhardingeb5eafe92010-12-06 16:29:22 -080083#include "xen-ops.h"
84
Juergen Gross054954e2014-11-28 11:53:58 +010085#define PMDS_PER_MID_PAGE (P2M_MID_PER_PAGE / PTRS_PER_PTE)
86
Jeremy Fitzhardinge448f28312010-12-15 13:19:33 +000087static void __init m2p_override_init(void);
88
Juergen Gross5b8e7d82014-11-28 11:53:55 +010089unsigned long *xen_p2m_addr __read_mostly;
90EXPORT_SYMBOL_GPL(xen_p2m_addr);
91unsigned long xen_p2m_size __read_mostly;
92EXPORT_SYMBOL_GPL(xen_p2m_size);
Jeremy Fitzhardingeb5eafe92010-12-06 16:29:22 -080093unsigned long xen_max_p2m_pfn __read_mostly;
Juergen Gross5b8e7d82014-11-28 11:53:55 +010094EXPORT_SYMBOL_GPL(xen_max_p2m_pfn);
Jeremy Fitzhardingeb5eafe92010-12-06 16:29:22 -080095
Juergen Gross054954e2014-11-28 11:53:58 +010096static DEFINE_SPINLOCK(p2m_update_lock);
97
Juergen Gross2c185682014-10-14 13:33:46 +020098static unsigned long *p2m_mid_missing_mfn;
99static unsigned long *p2m_top_mfn;
100static unsigned long **p2m_top_mfn_p;
Juergen Gross054954e2014-11-28 11:53:58 +0100101static unsigned long *p2m_missing;
102static unsigned long *p2m_identity;
103static pte_t *p2m_missing_pte;
104static pte_t *p2m_identity_pte;
Juergen Gross7108c9c2014-11-28 11:53:52 +0100105
Jeremy Fitzhardingeb5eafe92010-12-06 16:29:22 -0800106static inline unsigned p2m_top_index(unsigned long pfn)
107{
108 BUG_ON(pfn >= MAX_P2M_PFN);
109 return pfn / (P2M_MID_PER_PAGE * P2M_PER_PAGE);
110}
111
112static inline unsigned p2m_mid_index(unsigned long pfn)
113{
114 return (pfn / P2M_PER_PAGE) % P2M_MID_PER_PAGE;
115}
116
117static inline unsigned p2m_index(unsigned long pfn)
118{
119 return pfn % P2M_PER_PAGE;
120}
121
Jeremy Fitzhardingeb5eafe92010-12-06 16:29:22 -0800122static void p2m_top_mfn_init(unsigned long *top)
123{
124 unsigned i;
125
126 for (i = 0; i < P2M_TOP_PER_PAGE; i++)
127 top[i] = virt_to_mfn(p2m_mid_missing_mfn);
128}
129
130static void p2m_top_mfn_p_init(unsigned long **top)
131{
132 unsigned i;
133
134 for (i = 0; i < P2M_TOP_PER_PAGE; i++)
135 top[i] = p2m_mid_missing_mfn;
136}
137
David Vrabel3cb83e42014-01-07 11:44:32 +0000138static void p2m_mid_mfn_init(unsigned long *mid, unsigned long *leaf)
Jeremy Fitzhardingeb5eafe92010-12-06 16:29:22 -0800139{
140 unsigned i;
141
142 for (i = 0; i < P2M_MID_PER_PAGE; i++)
David Vrabel3cb83e42014-01-07 11:44:32 +0000143 mid[i] = virt_to_mfn(leaf);
Jeremy Fitzhardingeb5eafe92010-12-06 16:29:22 -0800144}
145
146static void p2m_init(unsigned long *p2m)
147{
148 unsigned i;
149
Juergen Gross054954e2014-11-28 11:53:58 +0100150 for (i = 0; i < P2M_PER_PAGE; i++)
Jeremy Fitzhardingeb5eafe92010-12-06 16:29:22 -0800151 p2m[i] = INVALID_P2M_ENTRY;
152}
153
Juergen Gross054954e2014-11-28 11:53:58 +0100154static void p2m_init_identity(unsigned long *p2m, unsigned long pfn)
155{
156 unsigned i;
157
158 for (i = 0; i < P2M_PER_PAGE; i++)
159 p2m[i] = IDENTITY_FRAME(pfn + i);
160}
161
Juergen Gross7108c9c2014-11-28 11:53:52 +0100162static void * __ref alloc_p2m_page(void)
163{
Juergen Gross7108c9c2014-11-28 11:53:52 +0100164 if (unlikely(!slab_is_available()))
165 return alloc_bootmem_align(PAGE_SIZE, PAGE_SIZE);
166
167 return (void *)__get_free_page(GFP_KERNEL | __GFP_REPEAT);
168}
169
170/* Only to be called in case of a race for a page just allocated! */
171static void free_p2m_page(void *p)
172{
173 BUG_ON(!slab_is_available());
174 free_page((unsigned long)p);
175}
176
Jeremy Fitzhardingeb5eafe92010-12-06 16:29:22 -0800177/*
178 * Build the parallel p2m_top_mfn and p2m_mid_mfn structures
179 *
180 * This is called both at boot time, and after resuming from suspend:
Juergen Gross2c185682014-10-14 13:33:46 +0200181 * - At boot time we're called rather early, and must use alloc_bootmem*()
Jeremy Fitzhardingeb5eafe92010-12-06 16:29:22 -0800182 * to allocate memory.
183 *
184 * - After resume we're called from within stop_machine, but the mfn
Juergen Gross2c185682014-10-14 13:33:46 +0200185 * tree should already be completely allocated.
Jeremy Fitzhardingeb5eafe92010-12-06 16:29:22 -0800186 */
Ian Campbell44b46c32011-02-11 16:37:41 +0000187void __ref xen_build_mfn_list_list(void)
Jeremy Fitzhardingeb5eafe92010-12-06 16:29:22 -0800188{
Juergen Gross054954e2014-11-28 11:53:58 +0100189 unsigned long pfn, mfn;
190 pte_t *ptep;
191 unsigned int level, topidx, mididx;
192 unsigned long *mid_mfn_p;
Jeremy Fitzhardingeb5eafe92010-12-06 16:29:22 -0800193
Konrad Rzeszutek Wilk696fd7c2013-12-15 12:37:46 -0500194 if (xen_feature(XENFEAT_auto_translated_physmap))
195 return;
196
Jeremy Fitzhardingeb5eafe92010-12-06 16:29:22 -0800197 /* Pre-initialize p2m_top_mfn to be completely missing */
198 if (p2m_top_mfn == NULL) {
Juergen Gross7108c9c2014-11-28 11:53:52 +0100199 p2m_mid_missing_mfn = alloc_p2m_page();
David Vrabel3cb83e42014-01-07 11:44:32 +0000200 p2m_mid_mfn_init(p2m_mid_missing_mfn, p2m_missing);
Jeremy Fitzhardingeb5eafe92010-12-06 16:29:22 -0800201
Juergen Gross7108c9c2014-11-28 11:53:52 +0100202 p2m_top_mfn_p = alloc_p2m_page();
Jeremy Fitzhardingeb5eafe92010-12-06 16:29:22 -0800203 p2m_top_mfn_p_init(p2m_top_mfn_p);
204
Juergen Gross7108c9c2014-11-28 11:53:52 +0100205 p2m_top_mfn = alloc_p2m_page();
Jeremy Fitzhardingeb5eafe92010-12-06 16:29:22 -0800206 p2m_top_mfn_init(p2m_top_mfn);
207 } else {
208 /* Reinitialise, mfn's all change after migration */
David Vrabel3cb83e42014-01-07 11:44:32 +0000209 p2m_mid_mfn_init(p2m_mid_missing_mfn, p2m_missing);
Jeremy Fitzhardingeb5eafe92010-12-06 16:29:22 -0800210 }
211
Juergen Gross054954e2014-11-28 11:53:58 +0100212 for (pfn = 0; pfn < xen_max_p2m_pfn && pfn < MAX_P2M_PFN;
213 pfn += P2M_PER_PAGE) {
214 topidx = p2m_top_index(pfn);
215 mididx = p2m_mid_index(pfn);
Jeremy Fitzhardingeb5eafe92010-12-06 16:29:22 -0800216
Jeremy Fitzhardingeb5eafe92010-12-06 16:29:22 -0800217 mid_mfn_p = p2m_top_mfn_p[topidx];
Juergen Gross054954e2014-11-28 11:53:58 +0100218 ptep = lookup_address((unsigned long)(xen_p2m_addr + pfn),
219 &level);
220 BUG_ON(!ptep || level != PG_LEVEL_4K);
221 mfn = pte_mfn(*ptep);
222 ptep = (pte_t *)((unsigned long)ptep & ~(PAGE_SIZE - 1));
Jeremy Fitzhardingeb5eafe92010-12-06 16:29:22 -0800223
224 /* Don't bother allocating any mfn mid levels if
225 * they're just missing, just update the stored mfn,
226 * since all could have changed over a migrate.
227 */
Juergen Gross054954e2014-11-28 11:53:58 +0100228 if (ptep == p2m_missing_pte || ptep == p2m_identity_pte) {
Jeremy Fitzhardingeb5eafe92010-12-06 16:29:22 -0800229 BUG_ON(mididx);
230 BUG_ON(mid_mfn_p != p2m_mid_missing_mfn);
231 p2m_top_mfn[topidx] = virt_to_mfn(p2m_mid_missing_mfn);
232 pfn += (P2M_MID_PER_PAGE - 1) * P2M_PER_PAGE;
233 continue;
234 }
235
236 if (mid_mfn_p == p2m_mid_missing_mfn) {
Juergen Gross7108c9c2014-11-28 11:53:52 +0100237 mid_mfn_p = alloc_p2m_page();
David Vrabel3cb83e42014-01-07 11:44:32 +0000238 p2m_mid_mfn_init(mid_mfn_p, p2m_missing);
Jeremy Fitzhardingeb5eafe92010-12-06 16:29:22 -0800239
240 p2m_top_mfn_p[topidx] = mid_mfn_p;
241 }
242
243 p2m_top_mfn[topidx] = virt_to_mfn(mid_mfn_p);
Juergen Gross054954e2014-11-28 11:53:58 +0100244 mid_mfn_p[mididx] = mfn;
Jeremy Fitzhardingeb5eafe92010-12-06 16:29:22 -0800245 }
246}
247
248void xen_setup_mfn_list_list(void)
249{
Mukesh Rathor4dd322b2013-12-31 14:02:44 -0500250 if (xen_feature(XENFEAT_auto_translated_physmap))
251 return;
252
Jeremy Fitzhardingeb5eafe92010-12-06 16:29:22 -0800253 BUG_ON(HYPERVISOR_shared_info == &xen_dummy_shared_info);
254
255 HYPERVISOR_shared_info->arch.pfn_to_mfn_frame_list_list =
256 virt_to_mfn(p2m_top_mfn);
257 HYPERVISOR_shared_info->arch.max_pfn = xen_max_p2m_pfn;
258}
259
260/* Set up p2m_top to point to the domain-builder provided p2m pages */
261void __init xen_build_dynamic_phys_to_machine(void)
262{
Jeremy Fitzhardingeb5eafe92010-12-06 16:29:22 -0800263 unsigned long pfn;
264
Konrad Rzeszutek Wilk696fd7c2013-12-15 12:37:46 -0500265 if (xen_feature(XENFEAT_auto_translated_physmap))
266 return;
267
Juergen Gross5b8e7d82014-11-28 11:53:55 +0100268 xen_p2m_addr = (unsigned long *)xen_start_info->mfn_list;
Juergen Gross054954e2014-11-28 11:53:58 +0100269 xen_p2m_size = ALIGN(xen_start_info->nr_pages, P2M_PER_PAGE);
270
271 for (pfn = xen_start_info->nr_pages; pfn < xen_p2m_size; pfn++)
272 xen_p2m_addr[pfn] = INVALID_P2M_ENTRY;
273
274 xen_max_p2m_pfn = xen_p2m_size;
275}
276
277#define P2M_TYPE_IDENTITY 0
278#define P2M_TYPE_MISSING 1
279#define P2M_TYPE_PFN 2
280#define P2M_TYPE_UNKNOWN 3
281
282static int xen_p2m_elem_type(unsigned long pfn)
283{
284 unsigned long mfn;
285
286 if (pfn >= xen_p2m_size)
287 return P2M_TYPE_IDENTITY;
288
289 mfn = xen_p2m_addr[pfn];
290
291 if (mfn == INVALID_P2M_ENTRY)
292 return P2M_TYPE_MISSING;
293
294 if (mfn & IDENTITY_FRAME_BIT)
295 return P2M_TYPE_IDENTITY;
296
297 return P2M_TYPE_PFN;
298}
299
300static void __init xen_rebuild_p2m_list(unsigned long *p2m)
301{
302 unsigned int i, chunk;
303 unsigned long pfn;
304 unsigned long *mfns;
305 pte_t *ptep;
306 pmd_t *pmdp;
307 int type;
Jeremy Fitzhardingeb5eafe92010-12-06 16:29:22 -0800308
Juergen Gross7108c9c2014-11-28 11:53:52 +0100309 p2m_missing = alloc_p2m_page();
Jeremy Fitzhardingeb5eafe92010-12-06 16:29:22 -0800310 p2m_init(p2m_missing);
Juergen Gross7108c9c2014-11-28 11:53:52 +0100311 p2m_identity = alloc_p2m_page();
David Vrabel3cb83e42014-01-07 11:44:32 +0000312 p2m_init(p2m_identity);
Jeremy Fitzhardingeb5eafe92010-12-06 16:29:22 -0800313
Juergen Gross054954e2014-11-28 11:53:58 +0100314 p2m_missing_pte = alloc_p2m_page();
315 paravirt_alloc_pte(&init_mm, __pa(p2m_missing_pte) >> PAGE_SHIFT);
316 p2m_identity_pte = alloc_p2m_page();
317 paravirt_alloc_pte(&init_mm, __pa(p2m_identity_pte) >> PAGE_SHIFT);
318 for (i = 0; i < PTRS_PER_PTE; i++) {
319 set_pte(p2m_missing_pte + i,
Juergen Gross2e917172014-11-28 11:53:59 +0100320 pfn_pte(PFN_DOWN(__pa(p2m_missing)), PAGE_KERNEL_RO));
Juergen Gross054954e2014-11-28 11:53:58 +0100321 set_pte(p2m_identity_pte + i,
Juergen Gross2e917172014-11-28 11:53:59 +0100322 pfn_pte(PFN_DOWN(__pa(p2m_identity)), PAGE_KERNEL_RO));
Juergen Gross054954e2014-11-28 11:53:58 +0100323 }
Jeremy Fitzhardingeb5eafe92010-12-06 16:29:22 -0800324
Juergen Gross054954e2014-11-28 11:53:58 +0100325 for (pfn = 0; pfn < xen_max_p2m_pfn; pfn += chunk) {
Stefan Bader8e1b4cf2011-01-20 15:38:23 +0100326 /*
Juergen Gross054954e2014-11-28 11:53:58 +0100327 * Try to map missing/identity PMDs or p2m-pages if possible.
328 * We have to respect the structure of the mfn_list_list
329 * which will be built just afterwards.
330 * Chunk size to test is one p2m page if we are in the middle
331 * of a mfn_list_list mid page and the complete mid page area
332 * if we are at index 0 of the mid page. Please note that a
333 * mid page might cover more than one PMD, e.g. on 32 bit PAE
334 * kernels.
Stefan Bader8e1b4cf2011-01-20 15:38:23 +0100335 */
Juergen Gross054954e2014-11-28 11:53:58 +0100336 chunk = (pfn & (P2M_PER_PAGE * P2M_MID_PER_PAGE - 1)) ?
337 P2M_PER_PAGE : P2M_PER_PAGE * P2M_MID_PER_PAGE;
Stefan Bader8e1b4cf2011-01-20 15:38:23 +0100338
Juergen Gross054954e2014-11-28 11:53:58 +0100339 type = xen_p2m_elem_type(pfn);
340 i = 0;
341 if (type != P2M_TYPE_PFN)
342 for (i = 1; i < chunk; i++)
343 if (xen_p2m_elem_type(pfn + i) != type)
344 break;
345 if (i < chunk)
346 /* Reset to minimal chunk size. */
347 chunk = P2M_PER_PAGE;
348
349 if (type == P2M_TYPE_PFN || i < chunk) {
350 /* Use initial p2m page contents. */
Konrad Rzeszutek Wilk357a3cf2012-07-19 13:52:29 -0400351#ifdef CONFIG_X86_64
Juergen Gross054954e2014-11-28 11:53:58 +0100352 mfns = alloc_p2m_page();
353 copy_page(mfns, xen_p2m_addr + pfn);
Konrad Rzeszutek Wilk357a3cf2012-07-19 13:52:29 -0400354#else
Juergen Gross054954e2014-11-28 11:53:58 +0100355 mfns = xen_p2m_addr + pfn;
Konrad Rzeszutek Wilk357a3cf2012-07-19 13:52:29 -0400356#endif
Juergen Gross054954e2014-11-28 11:53:58 +0100357 ptep = populate_extra_pte((unsigned long)(p2m + pfn));
358 set_pte(ptep,
359 pfn_pte(PFN_DOWN(__pa(mfns)), PAGE_KERNEL));
360 continue;
361 }
362
363 if (chunk == P2M_PER_PAGE) {
364 /* Map complete missing or identity p2m-page. */
365 mfns = (type == P2M_TYPE_MISSING) ?
366 p2m_missing : p2m_identity;
367 ptep = populate_extra_pte((unsigned long)(p2m + pfn));
368 set_pte(ptep,
Juergen Gross2e917172014-11-28 11:53:59 +0100369 pfn_pte(PFN_DOWN(__pa(mfns)), PAGE_KERNEL_RO));
Juergen Gross054954e2014-11-28 11:53:58 +0100370 continue;
371 }
372
373 /* Complete missing or identity PMD(s) can be mapped. */
374 ptep = (type == P2M_TYPE_MISSING) ?
375 p2m_missing_pte : p2m_identity_pte;
376 for (i = 0; i < PMDS_PER_MID_PAGE; i++) {
377 pmdp = populate_extra_pmd(
378 (unsigned long)(p2m + pfn + i * PTRS_PER_PTE));
379 set_pmd(pmdp, __pmd(__pa(ptep) | _KERNPG_TABLE));
380 }
381 }
382}
383
384void __init xen_vmalloc_p2m_tree(void)
385{
386 static struct vm_struct vm;
387
388 vm.flags = VM_ALLOC;
389 vm.size = ALIGN(sizeof(unsigned long) * xen_max_p2m_pfn,
390 PMD_SIZE * PMDS_PER_MID_PAGE);
391 vm_area_register_early(&vm, PMD_SIZE * PMDS_PER_MID_PAGE);
392 pr_notice("p2m virtual area at %p, size is %lx\n", vm.addr, vm.size);
393
394 xen_max_p2m_pfn = vm.size / sizeof(unsigned long);
395
396 xen_rebuild_p2m_list(vm.addr);
397
398 xen_p2m_addr = vm.addr;
399 xen_p2m_size = xen_max_p2m_pfn;
400
401 xen_inv_extra_mem();
402
403 m2p_override_init();
404}
405
Jeremy Fitzhardingeb5eafe92010-12-06 16:29:22 -0800406unsigned long get_phys_to_machine(unsigned long pfn)
407{
Juergen Gross054954e2014-11-28 11:53:58 +0100408 pte_t *ptep;
409 unsigned int level;
Jeremy Fitzhardingeb5eafe92010-12-06 16:29:22 -0800410
Juergen Gross5b8e7d82014-11-28 11:53:55 +0100411 if (unlikely(pfn >= xen_p2m_size)) {
412 if (pfn < xen_max_p2m_pfn)
413 return xen_chk_extra_mem(pfn);
414
David Vrabel25b884a2014-01-03 15:46:10 +0000415 return IDENTITY_FRAME(pfn);
Juergen Gross5b8e7d82014-11-28 11:53:55 +0100416 }
Jeremy Fitzhardingeb5eafe92010-12-06 16:29:22 -0800417
Juergen Gross054954e2014-11-28 11:53:58 +0100418 ptep = lookup_address((unsigned long)(xen_p2m_addr + pfn), &level);
419 BUG_ON(!ptep || level != PG_LEVEL_4K);
Jeremy Fitzhardingeb5eafe92010-12-06 16:29:22 -0800420
Konrad Rzeszutek Wilkf4cec352011-01-18 20:15:21 -0500421 /*
422 * The INVALID_P2M_ENTRY is filled in both p2m_*identity
423 * and in p2m_*missing, so returning the INVALID_P2M_ENTRY
424 * would be wrong.
425 */
Juergen Gross054954e2014-11-28 11:53:58 +0100426 if (pte_pfn(*ptep) == PFN_DOWN(__pa(p2m_identity)))
Konrad Rzeszutek Wilkf4cec352011-01-18 20:15:21 -0500427 return IDENTITY_FRAME(pfn);
428
Juergen Gross054954e2014-11-28 11:53:58 +0100429 return xen_p2m_addr[pfn];
Jeremy Fitzhardingeb5eafe92010-12-06 16:29:22 -0800430}
431EXPORT_SYMBOL_GPL(get_phys_to_machine);
432
Konrad Rzeszutek Wilka3118be2012-06-28 22:12:36 -0400433/*
Juergen Gross054954e2014-11-28 11:53:58 +0100434 * Allocate new pmd(s). It is checked whether the old pmd is still in place.
435 * If not, nothing is changed. This is okay as the only reason for allocating
436 * a new pmd is to replace p2m_missing_pte or p2m_identity_pte by a individual
437 * pmd. In case of PAE/x86-32 there are multiple pmds to allocate!
438 */
439static pte_t *alloc_p2m_pmd(unsigned long addr, pte_t *ptep, pte_t *pte_pg)
440{
441 pte_t *ptechk;
442 pte_t *pteret = ptep;
443 pte_t *pte_newpg[PMDS_PER_MID_PAGE];
444 pmd_t *pmdp;
445 unsigned int level;
446 unsigned long flags;
447 unsigned long vaddr;
448 int i;
449
450 /* Do all allocations first to bail out in error case. */
451 for (i = 0; i < PMDS_PER_MID_PAGE; i++) {
452 pte_newpg[i] = alloc_p2m_page();
453 if (!pte_newpg[i]) {
454 for (i--; i >= 0; i--)
455 free_p2m_page(pte_newpg[i]);
456
457 return NULL;
458 }
459 }
460
461 vaddr = addr & ~(PMD_SIZE * PMDS_PER_MID_PAGE - 1);
462
463 for (i = 0; i < PMDS_PER_MID_PAGE; i++) {
464 copy_page(pte_newpg[i], pte_pg);
465 paravirt_alloc_pte(&init_mm, __pa(pte_newpg[i]) >> PAGE_SHIFT);
466
467 pmdp = lookup_pmd_address(vaddr);
468 BUG_ON(!pmdp);
469
470 spin_lock_irqsave(&p2m_update_lock, flags);
471
472 ptechk = lookup_address(vaddr, &level);
473 if (ptechk == pte_pg) {
474 set_pmd(pmdp,
475 __pmd(__pa(pte_newpg[i]) | _KERNPG_TABLE));
476 if (vaddr == (addr & ~(PMD_SIZE - 1)))
477 pteret = pte_offset_kernel(pmdp, addr);
478 pte_newpg[i] = NULL;
479 }
480
481 spin_unlock_irqrestore(&p2m_update_lock, flags);
482
483 if (pte_newpg[i]) {
484 paravirt_release_pte(__pa(pte_newpg[i]) >> PAGE_SHIFT);
485 free_p2m_page(pte_newpg[i]);
486 }
487
488 vaddr += PMD_SIZE;
489 }
490
491 return pteret;
492}
493
494/*
Jeremy Fitzhardingeb5eafe92010-12-06 16:29:22 -0800495 * Fully allocate the p2m structure for a given pfn. We need to check
496 * that both the top and mid levels are allocated, and make sure the
497 * parallel mfn tree is kept in sync. We may race with other cpus, so
498 * the new pages are installed with cmpxchg; if we lose the race then
499 * simply free the page we allocated and use the one that's there.
500 */
501static bool alloc_p2m(unsigned long pfn)
502{
503 unsigned topidx, mididx;
Jeremy Fitzhardingeb5eafe92010-12-06 16:29:22 -0800504 unsigned long *top_mfn_p, *mid_mfn;
Juergen Gross054954e2014-11-28 11:53:58 +0100505 pte_t *ptep, *pte_pg;
506 unsigned int level;
507 unsigned long flags;
508 unsigned long addr = (unsigned long)(xen_p2m_addr + pfn);
509 unsigned long p2m_pfn;
Jeremy Fitzhardingeb5eafe92010-12-06 16:29:22 -0800510
511 topidx = p2m_top_index(pfn);
512 mididx = p2m_mid_index(pfn);
513
Juergen Gross054954e2014-11-28 11:53:58 +0100514 ptep = lookup_address(addr, &level);
515 BUG_ON(!ptep || level != PG_LEVEL_4K);
516 pte_pg = (pte_t *)((unsigned long)ptep & ~(PAGE_SIZE - 1));
Jeremy Fitzhardingeb5eafe92010-12-06 16:29:22 -0800517
Juergen Gross054954e2014-11-28 11:53:58 +0100518 if (pte_pg == p2m_missing_pte || pte_pg == p2m_identity_pte) {
519 /* PMD level is missing, allocate a new one */
520 ptep = alloc_p2m_pmd(addr, ptep, pte_pg);
521 if (!ptep)
Jeremy Fitzhardingeb5eafe92010-12-06 16:29:22 -0800522 return false;
Jeremy Fitzhardingeb5eafe92010-12-06 16:29:22 -0800523 }
524
Juergen Gross054954e2014-11-28 11:53:58 +0100525 if (p2m_top_mfn) {
526 top_mfn_p = &p2m_top_mfn[topidx];
527 mid_mfn = ACCESS_ONCE(p2m_top_mfn_p[topidx]);
Jeremy Fitzhardingeb5eafe92010-12-06 16:29:22 -0800528
Juergen Gross054954e2014-11-28 11:53:58 +0100529 BUG_ON(virt_to_mfn(mid_mfn) != *top_mfn_p);
Jeremy Fitzhardingeb5eafe92010-12-06 16:29:22 -0800530
Juergen Gross054954e2014-11-28 11:53:58 +0100531 if (mid_mfn == p2m_mid_missing_mfn) {
532 /* Separately check the mid mfn level */
533 unsigned long missing_mfn;
534 unsigned long mid_mfn_mfn;
535 unsigned long old_mfn;
Jeremy Fitzhardingeb5eafe92010-12-06 16:29:22 -0800536
Juergen Gross054954e2014-11-28 11:53:58 +0100537 mid_mfn = alloc_p2m_page();
538 if (!mid_mfn)
539 return false;
Jeremy Fitzhardingeb5eafe92010-12-06 16:29:22 -0800540
Juergen Gross054954e2014-11-28 11:53:58 +0100541 p2m_mid_mfn_init(mid_mfn, p2m_missing);
Jeremy Fitzhardingeb5eafe92010-12-06 16:29:22 -0800542
Juergen Gross054954e2014-11-28 11:53:58 +0100543 missing_mfn = virt_to_mfn(p2m_mid_missing_mfn);
544 mid_mfn_mfn = virt_to_mfn(mid_mfn);
545 old_mfn = cmpxchg(top_mfn_p, missing_mfn, mid_mfn_mfn);
546 if (old_mfn != missing_mfn) {
547 free_p2m_page(mid_mfn);
548 mid_mfn = mfn_to_virt(old_mfn);
549 } else {
550 p2m_top_mfn_p[topidx] = mid_mfn;
551 }
Juergen Gross239af7c2014-10-14 11:00:18 +0200552 }
Juergen Gross054954e2014-11-28 11:53:58 +0100553 } else {
554 mid_mfn = NULL;
Jeremy Fitzhardingeb5eafe92010-12-06 16:29:22 -0800555 }
556
Juergen Gross054954e2014-11-28 11:53:58 +0100557 p2m_pfn = pte_pfn(ACCESS_ONCE(*ptep));
558 if (p2m_pfn == PFN_DOWN(__pa(p2m_identity)) ||
559 p2m_pfn == PFN_DOWN(__pa(p2m_missing))) {
Jeremy Fitzhardingeb5eafe92010-12-06 16:29:22 -0800560 /* p2m leaf page is missing */
561 unsigned long *p2m;
562
563 p2m = alloc_p2m_page();
564 if (!p2m)
565 return false;
566
Juergen Gross054954e2014-11-28 11:53:58 +0100567 if (p2m_pfn == PFN_DOWN(__pa(p2m_missing)))
568 p2m_init(p2m);
Jeremy Fitzhardingeb5eafe92010-12-06 16:29:22 -0800569 else
Juergen Gross054954e2014-11-28 11:53:58 +0100570 p2m_init_identity(p2m, pfn);
571
572 spin_lock_irqsave(&p2m_update_lock, flags);
573
574 if (pte_pfn(*ptep) == p2m_pfn) {
575 set_pte(ptep,
576 pfn_pte(PFN_DOWN(__pa(p2m)), PAGE_KERNEL));
577 if (mid_mfn)
578 mid_mfn[mididx] = virt_to_mfn(p2m);
579 p2m = NULL;
580 }
581
582 spin_unlock_irqrestore(&p2m_update_lock, flags);
583
584 if (p2m)
585 free_p2m_page(p2m);
Jeremy Fitzhardingeb5eafe92010-12-06 16:29:22 -0800586 }
587
588 return true;
589}
590
Randy Dunlapb83c6e52011-03-24 13:34:32 -0700591unsigned long __init set_phys_range_identity(unsigned long pfn_s,
Konrad Rzeszutek Wilkf4cec352011-01-18 20:15:21 -0500592 unsigned long pfn_e)
593{
594 unsigned long pfn;
595
Juergen Gross5b8e7d82014-11-28 11:53:55 +0100596 if (unlikely(pfn_s >= xen_p2m_size))
Konrad Rzeszutek Wilkf4cec352011-01-18 20:15:21 -0500597 return 0;
598
599 if (unlikely(xen_feature(XENFEAT_auto_translated_physmap)))
600 return pfn_e - pfn_s;
601
602 if (pfn_s > pfn_e)
603 return 0;
604
Juergen Gross5b8e7d82014-11-28 11:53:55 +0100605 if (pfn_e > xen_p2m_size)
606 pfn_e = xen_p2m_size;
David Vrabela9b5bff2014-01-06 11:55:13 +0000607
Juergen Gross5b8e7d82014-11-28 11:53:55 +0100608 for (pfn = pfn_s; pfn < pfn_e; pfn++)
609 xen_p2m_addr[pfn] = IDENTITY_FRAME(pfn);
Konrad Rzeszutek Wilkf4cec352011-01-18 20:15:21 -0500610
611 return pfn - pfn_s;
612}
613
Jeremy Fitzhardingeb5eafe92010-12-06 16:29:22 -0800614bool __set_phys_to_machine(unsigned long pfn, unsigned long mfn)
615{
Juergen Gross054954e2014-11-28 11:53:58 +0100616 pte_t *ptep;
617 unsigned int level;
Jeremy Fitzhardingeb5eafe92010-12-06 16:29:22 -0800618
Stefano Stabellini2f558d42013-10-09 20:39:01 +0000619 /* don't track P2M changes in autotranslate guests */
620 if (unlikely(xen_feature(XENFEAT_auto_translated_physmap)))
Konrad Rzeszutek Wilk6eaa4122011-01-18 20:09:41 -0500621 return true;
Stefano Stabellini2f558d42013-10-09 20:39:01 +0000622
Juergen Gross5b8e7d82014-11-28 11:53:55 +0100623 if (unlikely(pfn >= xen_p2m_size)) {
Jeremy Fitzhardingeb5eafe92010-12-06 16:29:22 -0800624 BUG_ON(mfn != INVALID_P2M_ENTRY);
625 return true;
626 }
627
Juergen Gross2e917172014-11-28 11:53:59 +0100628 if (likely(!__put_user(mfn, xen_p2m_addr + pfn)))
629 return true;
630
Juergen Gross054954e2014-11-28 11:53:58 +0100631 ptep = lookup_address((unsigned long)(xen_p2m_addr + pfn), &level);
632 BUG_ON(!ptep || level != PG_LEVEL_4K);
Jeremy Fitzhardingeb5eafe92010-12-06 16:29:22 -0800633
Juergen Gross054954e2014-11-28 11:53:58 +0100634 if (pte_pfn(*ptep) == PFN_DOWN(__pa(p2m_missing)))
Jeremy Fitzhardingeb5eafe92010-12-06 16:29:22 -0800635 return mfn == INVALID_P2M_ENTRY;
636
Juergen Gross054954e2014-11-28 11:53:58 +0100637 if (pte_pfn(*ptep) == PFN_DOWN(__pa(p2m_identity)))
638 return mfn == IDENTITY_FRAME(pfn);
639
Juergen Gross2e917172014-11-28 11:53:59 +0100640 return false;
Jeremy Fitzhardingeb5eafe92010-12-06 16:29:22 -0800641}
642
643bool set_phys_to_machine(unsigned long pfn, unsigned long mfn)
644{
Juergen Gross054954e2014-11-28 11:53:58 +0100645 if (unlikely(!__set_phys_to_machine(pfn, mfn))) {
Jeremy Fitzhardingeb5eafe92010-12-06 16:29:22 -0800646 if (!alloc_p2m(pfn))
647 return false;
648
Juergen Gross054954e2014-11-28 11:53:58 +0100649 return __set_phys_to_machine(pfn, mfn);
Jeremy Fitzhardingeb5eafe92010-12-06 16:29:22 -0800650 }
651
652 return true;
653}
Jeremy Fitzhardinge448f28312010-12-15 13:19:33 +0000654
655#define M2P_OVERRIDE_HASH_SHIFT 10
656#define M2P_OVERRIDE_HASH (1 << M2P_OVERRIDE_HASH_SHIFT)
657
Juergen Gross97f45332014-11-28 11:53:54 +0100658static struct list_head *m2p_overrides;
Jeremy Fitzhardinge448f28312010-12-15 13:19:33 +0000659static DEFINE_SPINLOCK(m2p_override_lock);
660
661static void __init m2p_override_init(void)
662{
663 unsigned i;
664
Juergen Gross97f45332014-11-28 11:53:54 +0100665 m2p_overrides = alloc_bootmem_align(
666 sizeof(*m2p_overrides) * M2P_OVERRIDE_HASH,
667 sizeof(unsigned long));
Jeremy Fitzhardinge448f28312010-12-15 13:19:33 +0000668
669 for (i = 0; i < M2P_OVERRIDE_HASH; i++)
670 INIT_LIST_HEAD(&m2p_overrides[i]);
671}
672
673static unsigned long mfn_hash(unsigned long mfn)
674{
675 return hash_long(mfn, M2P_OVERRIDE_HASH_SHIFT);
676}
677
Juergen Gross820c4db2014-11-28 11:53:51 +0100678/* Add an MFN override for a particular page */
679static int m2p_add_override(unsigned long mfn, struct page *page,
680 struct gnttab_map_grant_ref *kmap_op)
681{
682 unsigned long flags;
683 unsigned long pfn;
684 unsigned long uninitialized_var(address);
685 unsigned level;
686 pte_t *ptep = NULL;
687
688 pfn = page_to_pfn(page);
689 if (!PageHighMem(page)) {
690 address = (unsigned long)__va(pfn << PAGE_SHIFT);
691 ptep = lookup_address(address, &level);
692 if (WARN(ptep == NULL || level != PG_LEVEL_4K,
693 "m2p_add_override: pfn %lx not mapped", pfn))
694 return -EINVAL;
695 }
696
697 if (kmap_op != NULL) {
698 if (!PageHighMem(page)) {
699 struct multicall_space mcs =
700 xen_mc_entry(sizeof(*kmap_op));
701
702 MULTI_grant_table_op(mcs.mc,
703 GNTTABOP_map_grant_ref, kmap_op, 1);
704
705 xen_mc_issue(PARAVIRT_LAZY_MMU);
706 }
707 }
708 spin_lock_irqsave(&m2p_override_lock, flags);
709 list_add(&page->lru, &m2p_overrides[mfn_hash(mfn)]);
710 spin_unlock_irqrestore(&m2p_override_lock, flags);
711
712 /* p2m(m2p(mfn)) == mfn: the mfn is already present somewhere in
713 * this domain. Set the FOREIGN_FRAME_BIT in the p2m for the other
714 * pfn so that the following mfn_to_pfn(mfn) calls will return the
715 * pfn from the m2p_override (the backend pfn) instead.
716 * We need to do this because the pages shared by the frontend
717 * (xen-blkfront) can be already locked (lock_page, called by
718 * do_read_cache_page); when the userspace backend tries to use them
719 * with direct_IO, mfn_to_pfn returns the pfn of the frontend, so
720 * do_blockdev_direct_IO is going to try to lock the same pages
721 * again resulting in a deadlock.
722 * As a side effect get_user_pages_fast might not be safe on the
723 * frontend pages while they are being shared with the backend,
724 * because mfn_to_pfn (that ends up being called by GUPF) will
725 * return the backend pfn rather than the frontend pfn. */
726 pfn = mfn_to_pfn_no_overrides(mfn);
Juergen Gross0aad5682014-11-28 11:53:57 +0100727 if (__pfn_to_mfn(pfn) == mfn)
Juergen Gross820c4db2014-11-28 11:53:51 +0100728 set_phys_to_machine(pfn, FOREIGN_FRAME(mfn));
729
730 return 0;
731}
732
Zoltan Kiss1429d462014-02-27 15:55:30 +0000733int set_foreign_p2m_mapping(struct gnttab_map_grant_ref *map_ops,
734 struct gnttab_map_grant_ref *kmap_ops,
735 struct page **pages, unsigned int count)
736{
737 int i, ret = 0;
738 bool lazy = false;
739 pte_t *pte;
740
741 if (xen_feature(XENFEAT_auto_translated_physmap))
742 return 0;
743
744 if (kmap_ops &&
745 !in_interrupt() &&
746 paravirt_get_lazy_mode() == PARAVIRT_LAZY_NONE) {
747 arch_enter_lazy_mmu_mode();
748 lazy = true;
749 }
750
751 for (i = 0; i < count; i++) {
752 unsigned long mfn, pfn;
753
754 /* Do not add to override if the map failed. */
755 if (map_ops[i].status)
756 continue;
757
758 if (map_ops[i].flags & GNTMAP_contains_pte) {
Juergen Gross6f58d892014-11-28 11:53:50 +0100759 pte = (pte_t *)(mfn_to_virt(PFN_DOWN(map_ops[i].host_addr)) +
Zoltan Kiss1429d462014-02-27 15:55:30 +0000760 (map_ops[i].host_addr & ~PAGE_MASK));
761 mfn = pte_mfn(*pte);
762 } else {
763 mfn = PFN_DOWN(map_ops[i].dev_bus_addr);
764 }
765 pfn = page_to_pfn(pages[i]);
766
767 WARN_ON(PagePrivate(pages[i]));
768 SetPagePrivate(pages[i]);
769 set_page_private(pages[i], mfn);
770 pages[i]->index = pfn_to_mfn(pfn);
771
772 if (unlikely(!set_phys_to_machine(pfn, FOREIGN_FRAME(mfn)))) {
773 ret = -ENOMEM;
774 goto out;
775 }
776
777 if (kmap_ops) {
778 ret = m2p_add_override(mfn, pages[i], &kmap_ops[i]);
779 if (ret)
780 goto out;
781 }
782 }
783
784out:
785 if (lazy)
786 arch_leave_lazy_mmu_mode();
787
788 return ret;
789}
790EXPORT_SYMBOL_GPL(set_foreign_p2m_mapping);
791
Juergen Gross820c4db2014-11-28 11:53:51 +0100792static struct page *m2p_find_override(unsigned long mfn)
Jeremy Fitzhardinge448f28312010-12-15 13:19:33 +0000793{
794 unsigned long flags;
Juergen Gross97f45332014-11-28 11:53:54 +0100795 struct list_head *bucket;
Juergen Gross820c4db2014-11-28 11:53:51 +0100796 struct page *p, *ret;
Jeremy Fitzhardinge87f1d402010-12-13 14:42:30 +0000797
Juergen Gross97f45332014-11-28 11:53:54 +0100798 if (unlikely(!m2p_overrides))
799 return NULL;
800
Juergen Gross820c4db2014-11-28 11:53:51 +0100801 ret = NULL;
Juergen Gross97f45332014-11-28 11:53:54 +0100802 bucket = &m2p_overrides[mfn_hash(mfn)];
Daniel De Graafb2542442011-03-24 08:10:07 -0400803
Juergen Gross820c4db2014-11-28 11:53:51 +0100804 spin_lock_irqsave(&m2p_override_lock, flags);
Stefano Stabellini0930bba2011-09-29 11:57:56 +0100805
Juergen Gross820c4db2014-11-28 11:53:51 +0100806 list_for_each_entry(p, bucket, lru) {
807 if (page_private(p) == mfn) {
808 ret = p;
809 break;
Stefano Stabellini0930bba2011-09-29 11:57:56 +0100810 }
Stefano Stabellini0930bba2011-09-29 11:57:56 +0100811 }
Juergen Gross820c4db2014-11-28 11:53:51 +0100812
Jeremy Fitzhardinge448f28312010-12-15 13:19:33 +0000813 spin_unlock_irqrestore(&m2p_override_lock, flags);
Jeremy Fitzhardinge87f1d402010-12-13 14:42:30 +0000814
Zoltan Kiss1429d462014-02-27 15:55:30 +0000815 return ret;
816}
Zoltan Kiss1429d462014-02-27 15:55:30 +0000817
Juergen Gross820c4db2014-11-28 11:53:51 +0100818static int m2p_remove_override(struct page *page,
819 struct gnttab_map_grant_ref *kmap_op,
820 unsigned long mfn)
Jeremy Fitzhardinge448f28312010-12-15 13:19:33 +0000821{
822 unsigned long flags;
Stefano Stabellini9b705f02010-12-10 14:52:45 +0000823 unsigned long pfn;
Ian Campbell6b08cfe2011-02-11 15:23:58 +0000824 unsigned long uninitialized_var(address);
Jeremy Fitzhardinge87f1d402010-12-13 14:42:30 +0000825 unsigned level;
826 pte_t *ptep = NULL;
Stefano Stabellini9b705f02010-12-10 14:52:45 +0000827
828 pfn = page_to_pfn(page);
Jeremy Fitzhardinge87f1d402010-12-13 14:42:30 +0000829
830 if (!PageHighMem(page)) {
831 address = (unsigned long)__va(pfn << PAGE_SHIFT);
832 ptep = lookup_address(address, &level);
833
834 if (WARN(ptep == NULL || level != PG_LEVEL_4K,
Juergen Gross6f58d892014-11-28 11:53:50 +0100835 "m2p_remove_override: pfn %lx not mapped", pfn))
Jeremy Fitzhardinge87f1d402010-12-13 14:42:30 +0000836 return -EINVAL;
837 }
Stefano Stabellini9b705f02010-12-10 14:52:45 +0000838
Jeremy Fitzhardinge448f28312010-12-15 13:19:33 +0000839 spin_lock_irqsave(&m2p_override_lock, flags);
840 list_del(&page->lru);
841 spin_unlock_irqrestore(&m2p_override_lock, flags);
Jeremy Fitzhardinge87f1d402010-12-13 14:42:30 +0000842
Stefano Stabellini2fc136e2012-09-12 12:44:30 +0100843 if (kmap_op != NULL) {
Stefano Stabellini0930bba2011-09-29 11:57:56 +0100844 if (!PageHighMem(page)) {
845 struct multicall_space mcs;
Stefano Stabelliniee072642013-07-23 17:23:54 +0000846 struct gnttab_unmap_and_replace *unmap_op;
847 struct page *scratch_page = get_balloon_scratch_page();
848 unsigned long scratch_page_address = (unsigned long)
849 __va(page_to_pfn(scratch_page) << PAGE_SHIFT);
Stefano Stabellini0930bba2011-09-29 11:57:56 +0100850
851 /*
852 * It might be that we queued all the m2p grant table
853 * hypercalls in a multicall, then m2p_remove_override
854 * get called before the multicall has actually been
855 * issued. In this case handle is going to -1 because
856 * it hasn't been modified yet.
857 */
Stefano Stabellini2fc136e2012-09-12 12:44:30 +0100858 if (kmap_op->handle == -1)
Stefano Stabellini0930bba2011-09-29 11:57:56 +0100859 xen_mc_flush();
860 /*
Stefano Stabellini2fc136e2012-09-12 12:44:30 +0100861 * Now if kmap_op->handle is negative it means that the
Stefano Stabellini0930bba2011-09-29 11:57:56 +0100862 * hypercall actually returned an error.
863 */
Stefano Stabellini2fc136e2012-09-12 12:44:30 +0100864 if (kmap_op->handle == GNTST_general_error) {
Juergen Gross6f58d892014-11-28 11:53:50 +0100865 pr_warn("m2p_remove_override: pfn %lx mfn %lx, failed to modify kernel mappings",
866 pfn, mfn);
Boris Ostrovskyd7f8f482013-09-09 10:44:26 +0000867 put_balloon_scratch_page();
Stefano Stabellini0930bba2011-09-29 11:57:56 +0100868 return -1;
869 }
870
Boris Ostrovskyd7f8f482013-09-09 10:44:26 +0000871 xen_mc_batch();
872
873 mcs = __xen_mc_entry(
Juergen Gross6f58d892014-11-28 11:53:50 +0100874 sizeof(struct gnttab_unmap_and_replace));
Stefano Stabellini0930bba2011-09-29 11:57:56 +0100875 unmap_op = mcs.args;
Stefano Stabellini2fc136e2012-09-12 12:44:30 +0100876 unmap_op->host_addr = kmap_op->host_addr;
Stefano Stabelliniee072642013-07-23 17:23:54 +0000877 unmap_op->new_addr = scratch_page_address;
Stefano Stabellini2fc136e2012-09-12 12:44:30 +0100878 unmap_op->handle = kmap_op->handle;
Stefano Stabellini0930bba2011-09-29 11:57:56 +0100879
880 MULTI_grant_table_op(mcs.mc,
Juergen Gross6f58d892014-11-28 11:53:50 +0100881 GNTTABOP_unmap_and_replace, unmap_op, 1);
Stefano Stabellini0930bba2011-09-29 11:57:56 +0100882
Stefano Stabelliniee072642013-07-23 17:23:54 +0000883 mcs = __xen_mc_entry(0);
884 MULTI_update_va_mapping(mcs.mc, scratch_page_address,
Boris Ostrovskyd7f8f482013-09-09 10:44:26 +0000885 pfn_pte(page_to_pfn(scratch_page),
Stefano Stabelliniee072642013-07-23 17:23:54 +0000886 PAGE_KERNEL_RO), 0);
Boris Ostrovskyd7f8f482013-09-09 10:44:26 +0000887
Stefano Stabelliniee072642013-07-23 17:23:54 +0000888 xen_mc_issue(PARAVIRT_LAZY_MMU);
889
Stefano Stabellini2fc136e2012-09-12 12:44:30 +0100890 kmap_op->host_addr = 0;
Stefano Stabelliniee072642013-07-23 17:23:54 +0000891 put_balloon_scratch_page();
Stefano Stabellini0930bba2011-09-29 11:57:56 +0100892 }
Stefano Stabellini2fc136e2012-09-12 12:44:30 +0100893 }
Jeremy Fitzhardinge87f1d402010-12-13 14:42:30 +0000894
Stefano Stabellinib9e0d952012-05-23 18:57:20 +0100895 /* p2m(m2p(mfn)) == FOREIGN_FRAME(mfn): the mfn is already present
896 * somewhere in this domain, even before being added to the
897 * m2p_override (see comment above in m2p_add_override).
898 * If there are no other entries in the m2p_override corresponding
899 * to this mfn, then remove the FOREIGN_FRAME_BIT from the p2m for
900 * the original pfn (the one shared by the frontend): the backend
901 * cannot do any IO on this page anymore because it has been
902 * unshared. Removing the FOREIGN_FRAME_BIT from the p2m entry of
903 * the original pfn causes mfn_to_pfn(mfn) to return the frontend
904 * pfn again. */
905 mfn &= ~FOREIGN_FRAME_BIT;
David Vrabel01606762013-09-13 15:13:30 +0100906 pfn = mfn_to_pfn_no_overrides(mfn);
Juergen Gross0aad5682014-11-28 11:53:57 +0100907 if (__pfn_to_mfn(pfn) == FOREIGN_FRAME(mfn) &&
Stefano Stabellinib9e0d952012-05-23 18:57:20 +0100908 m2p_find_override(mfn) == NULL)
909 set_phys_to_machine(pfn, mfn);
910
Jeremy Fitzhardinge87f1d402010-12-13 14:42:30 +0000911 return 0;
Jeremy Fitzhardinge448f28312010-12-15 13:19:33 +0000912}
913
Juergen Gross820c4db2014-11-28 11:53:51 +0100914int clear_foreign_p2m_mapping(struct gnttab_unmap_grant_ref *unmap_ops,
915 struct gnttab_map_grant_ref *kmap_ops,
916 struct page **pages, unsigned int count)
Jeremy Fitzhardinge448f28312010-12-15 13:19:33 +0000917{
Juergen Gross820c4db2014-11-28 11:53:51 +0100918 int i, ret = 0;
919 bool lazy = false;
Jeremy Fitzhardinge448f28312010-12-15 13:19:33 +0000920
Juergen Gross820c4db2014-11-28 11:53:51 +0100921 if (xen_feature(XENFEAT_auto_translated_physmap))
922 return 0;
Jeremy Fitzhardinge448f28312010-12-15 13:19:33 +0000923
Juergen Gross820c4db2014-11-28 11:53:51 +0100924 if (kmap_ops &&
925 !in_interrupt() &&
926 paravirt_get_lazy_mode() == PARAVIRT_LAZY_NONE) {
927 arch_enter_lazy_mmu_mode();
928 lazy = true;
Jeremy Fitzhardinge448f28312010-12-15 13:19:33 +0000929 }
930
Juergen Gross820c4db2014-11-28 11:53:51 +0100931 for (i = 0; i < count; i++) {
Juergen Gross0aad5682014-11-28 11:53:57 +0100932 unsigned long mfn = __pfn_to_mfn(page_to_pfn(pages[i]));
Juergen Gross820c4db2014-11-28 11:53:51 +0100933 unsigned long pfn = page_to_pfn(pages[i]);
Jeremy Fitzhardinge448f28312010-12-15 13:19:33 +0000934
Juergen Gross820c4db2014-11-28 11:53:51 +0100935 if (mfn == INVALID_P2M_ENTRY || !(mfn & FOREIGN_FRAME_BIT)) {
936 ret = -EINVAL;
937 goto out;
938 }
939
940 set_page_private(pages[i], INVALID_P2M_ENTRY);
941 WARN_ON(!PagePrivate(pages[i]));
942 ClearPagePrivate(pages[i]);
943 set_phys_to_machine(pfn, pages[i]->index);
944
945 if (kmap_ops)
946 ret = m2p_remove_override(pages[i], &kmap_ops[i], mfn);
947 if (ret)
948 goto out;
949 }
950
951out:
952 if (lazy)
953 arch_leave_lazy_mmu_mode();
Jeremy Fitzhardinge448f28312010-12-15 13:19:33 +0000954 return ret;
955}
Juergen Gross820c4db2014-11-28 11:53:51 +0100956EXPORT_SYMBOL_GPL(clear_foreign_p2m_mapping);
Jeremy Fitzhardinge448f28312010-12-15 13:19:33 +0000957
958unsigned long m2p_find_override_pfn(unsigned long mfn, unsigned long pfn)
959{
960 struct page *p = m2p_find_override(mfn);
961 unsigned long ret = pfn;
962
963 if (p)
964 ret = page_to_pfn(p);
965
966 return ret;
967}
Konrad Rzeszutek Wilke1b478e2011-01-11 15:09:16 -0500968EXPORT_SYMBOL_GPL(m2p_find_override_pfn);
Konrad Rzeszutek Wilk2222e712010-12-22 08:57:30 -0500969
970#ifdef CONFIG_XEN_DEBUG_FS
Konrad Rzeszutek Wilka867db12011-09-23 16:32:47 -0400971#include <linux/debugfs.h>
972#include "debugfs.h"
973static int p2m_dump_show(struct seq_file *m, void *v)
Konrad Rzeszutek Wilk2222e712010-12-22 08:57:30 -0500974{
Konrad Rzeszutek Wilka491dbe2011-10-03 12:35:26 -0400975 static const char * const type_name[] = {
Juergen Gross054954e2014-11-28 11:53:58 +0100976 [P2M_TYPE_IDENTITY] = "identity",
977 [P2M_TYPE_MISSING] = "missing",
978 [P2M_TYPE_PFN] = "pfn",
979 [P2M_TYPE_UNKNOWN] = "abnormal"};
980 unsigned long pfn, first_pfn;
981 int type, prev_type;
Konrad Rzeszutek Wilk2222e712010-12-22 08:57:30 -0500982
Juergen Gross054954e2014-11-28 11:53:58 +0100983 prev_type = xen_p2m_elem_type(0);
984 first_pfn = 0;
Konrad Rzeszutek Wilk2222e712010-12-22 08:57:30 -0500985
Juergen Gross054954e2014-11-28 11:53:58 +0100986 for (pfn = 0; pfn < xen_p2m_size; pfn++) {
987 type = xen_p2m_elem_type(pfn);
988 if (type != prev_type) {
989 seq_printf(m, " [0x%lx->0x%lx] %s\n", first_pfn, pfn,
990 type_name[prev_type]);
Konrad Rzeszutek Wilk2222e712010-12-22 08:57:30 -0500991 prev_type = type;
Juergen Gross054954e2014-11-28 11:53:58 +0100992 first_pfn = pfn;
Konrad Rzeszutek Wilk2222e712010-12-22 08:57:30 -0500993 }
994 }
Juergen Gross054954e2014-11-28 11:53:58 +0100995 seq_printf(m, " [0x%lx->0x%lx] %s\n", first_pfn, pfn,
996 type_name[prev_type]);
Konrad Rzeszutek Wilk2222e712010-12-22 08:57:30 -0500997 return 0;
Konrad Rzeszutek Wilk2222e712010-12-22 08:57:30 -0500998}
Konrad Rzeszutek Wilka867db12011-09-23 16:32:47 -0400999
1000static int p2m_dump_open(struct inode *inode, struct file *filp)
1001{
1002 return single_open(filp, p2m_dump_show, NULL);
1003}
1004
1005static const struct file_operations p2m_dump_fops = {
1006 .open = p2m_dump_open,
1007 .read = seq_read,
1008 .llseek = seq_lseek,
1009 .release = single_release,
1010};
1011
1012static struct dentry *d_mmu_debug;
1013
1014static int __init xen_p2m_debugfs(void)
1015{
1016 struct dentry *d_xen = xen_init_debugfs();
1017
1018 if (d_xen == NULL)
1019 return -ENOMEM;
1020
1021 d_mmu_debug = debugfs_create_dir("mmu", d_xen);
1022
1023 debugfs_create_file("p2m", 0600, d_mmu_debug, NULL, &p2m_dump_fops);
1024 return 0;
1025}
1026fs_initcall(xen_p2m_debugfs);
1027#endif /* CONFIG_XEN_DEBUG_FS */