@@ -111,6 +111,51 @@ static pud_t level3_user_vsyscall[PTRS_PER_PUD] __page_aligned_bss;
111
111
*/
112
112
static DEFINE_SPINLOCK (xen_reservation_lock );
113
113
114
+ /* Protected by xen_reservation_lock. */
115
+ #define MIN_CONTIG_ORDER 9 /* 2MB */
116
+ static unsigned int discontig_frames_order = MIN_CONTIG_ORDER ;
117
+ static unsigned long discontig_frames_early [1UL << MIN_CONTIG_ORDER ] __initdata ;
118
+ static unsigned long * discontig_frames __refdata = discontig_frames_early ;
119
+ static bool discontig_frames_dyn ;
120
+
121
+ static int alloc_discontig_frames (unsigned int order )
122
+ {
123
+ unsigned long * new_array , * old_array ;
124
+ unsigned int old_order ;
125
+ unsigned long flags ;
126
+
127
+ BUG_ON (order < MIN_CONTIG_ORDER );
128
+ BUILD_BUG_ON (sizeof (discontig_frames_early ) != PAGE_SIZE );
129
+
130
+ new_array = (unsigned long * )__get_free_pages (GFP_KERNEL ,
131
+ order - MIN_CONTIG_ORDER );
132
+ if (!new_array )
133
+ return - ENOMEM ;
134
+
135
+ spin_lock_irqsave (& xen_reservation_lock , flags );
136
+
137
+ old_order = discontig_frames_order ;
138
+
139
+ if (order > discontig_frames_order || !discontig_frames_dyn ) {
140
+ if (!discontig_frames_dyn )
141
+ old_array = NULL ;
142
+ else
143
+ old_array = discontig_frames ;
144
+
145
+ discontig_frames = new_array ;
146
+ discontig_frames_order = order ;
147
+ discontig_frames_dyn = true;
148
+ } else {
149
+ old_array = new_array ;
150
+ }
151
+
152
+ spin_unlock_irqrestore (& xen_reservation_lock , flags );
153
+
154
+ free_pages ((unsigned long )old_array , old_order - MIN_CONTIG_ORDER );
155
+
156
+ return 0 ;
157
+ }
158
+
114
159
/*
115
160
* Note about cr3 (pagetable base) values:
116
161
*
@@ -814,6 +859,9 @@ static void __init xen_after_bootmem(void)
814
859
SetPagePinned (virt_to_page (level3_user_vsyscall ));
815
860
#endif
816
861
xen_pgd_walk (& init_mm , xen_mark_pinned , FIXADDR_TOP );
862
+
863
+ if (alloc_discontig_frames (MIN_CONTIG_ORDER ))
864
+ BUG ();
817
865
}
818
866
819
867
static void xen_unpin_page (struct mm_struct * mm , struct page * page ,
@@ -2203,10 +2251,6 @@ void __init xen_init_mmu_ops(void)
2203
2251
memset (dummy_mapping , 0xff , PAGE_SIZE );
2204
2252
}
2205
2253
2206
- /* Protected by xen_reservation_lock. */
2207
- #define MAX_CONTIG_ORDER 9 /* 2MB */
2208
- static unsigned long discontig_frames [1 <<MAX_CONTIG_ORDER ];
2209
-
2210
2254
#define VOID_PTE (mfn_pte(0, __pgprot(0)))
2211
2255
static void xen_zap_pfn_range (unsigned long vaddr , unsigned int order ,
2212
2256
unsigned long * in_frames ,
@@ -2323,18 +2367,25 @@ int xen_create_contiguous_region(phys_addr_t pstart, unsigned int order,
2323
2367
unsigned int address_bits ,
2324
2368
dma_addr_t * dma_handle )
2325
2369
{
2326
- unsigned long * in_frames = discontig_frames , out_frame ;
2370
+ unsigned long * in_frames , out_frame ;
2327
2371
unsigned long flags ;
2328
2372
int success ;
2329
2373
unsigned long vstart = (unsigned long )phys_to_virt (pstart );
2330
2374
2331
- if (unlikely (order > MAX_CONTIG_ORDER ))
2332
- return - ENOMEM ;
2375
+ if (unlikely (order > discontig_frames_order )) {
2376
+ if (!discontig_frames_dyn )
2377
+ return - ENOMEM ;
2378
+
2379
+ if (alloc_discontig_frames (order ))
2380
+ return - ENOMEM ;
2381
+ }
2333
2382
2334
2383
memset ((void * ) vstart , 0 , PAGE_SIZE << order );
2335
2384
2336
2385
spin_lock_irqsave (& xen_reservation_lock , flags );
2337
2386
2387
+ in_frames = discontig_frames ;
2388
+
2338
2389
/* 1. Zap current PTEs, remembering MFNs. */
2339
2390
xen_zap_pfn_range (vstart , order , in_frames , NULL );
2340
2391
@@ -2358,19 +2409,21 @@ int xen_create_contiguous_region(phys_addr_t pstart, unsigned int order,
2358
2409
2359
2410
void xen_destroy_contiguous_region (phys_addr_t pstart , unsigned int order )
2360
2411
{
2361
- unsigned long * out_frames = discontig_frames , in_frame ;
2412
+ unsigned long * out_frames , in_frame ;
2362
2413
unsigned long flags ;
2363
2414
int success ;
2364
2415
unsigned long vstart ;
2365
2416
2366
- if (unlikely (order > MAX_CONTIG_ORDER ))
2417
+ if (unlikely (order > discontig_frames_order ))
2367
2418
return ;
2368
2419
2369
2420
vstart = (unsigned long )phys_to_virt (pstart );
2370
2421
memset ((void * ) vstart , 0 , PAGE_SIZE << order );
2371
2422
2372
2423
spin_lock_irqsave (& xen_reservation_lock , flags );
2373
2424
2425
+ out_frames = discontig_frames ;
2426
+
2374
2427
/* 1. Find start MFN of contiguous extent. */
2375
2428
in_frame = virt_to_mfn ((void * )vstart );
2376
2429
0 commit comments