more correct pfn_valid()
PATCH 1/1 more correct pfn_valid()
Context: x86_64, 6gig ram.
(XEN) Physical RAM map:
(XEN) 0000000000000000 - 000000000009dc00 (usable) (XEN) 000000000009dc00 - 00000000000a0000 (reserved) (XEN) 00000000000d0000 - 0000000000100000 (reserved) (XEN) 0000000000100000 - 00000000dff60000 (usable) (XEN) 00000000dff60000 - 00000000dff72000 (ACPI data) (XEN) 00000000dff72000 - 00000000dff80000 (ACPI NVS) (XEN) 00000000dff80000 - 00000000e0000000 (reserved) (XEN) 00000000fec00000 - 00000000fec00400 (reserved) (XEN) 00000000fee00000 - 00000000fee01000 (reserved) (XEN) 00000000fff80000 - 0000000100000000 (reserved) (XEN) 0000000100000000 - 0000000180000000 (usable) <---- above hole
Notice there is now memory above the pci hole.
get_page_from_l1e() has the following code:
/* No reference counting for out-of-range I/O pages. */
if ( !pfn_valid(mfn) )
return 1;where:
#define pfn_valid(_pfn) ((_pfn) < max_page)
Since max_page is now above the out-of-range io, the pfn_valid() returns "valid". And hence get_page() is called, but returns an error given that the page count is zero ("not allocated") which ultimately ends up that the ioremap() for several device drivers fails with ENOMEM.
While attached patch fixes this problem (from empirical evidence), there may be a better solution.
sRp
Signature · 2 lines
Scott Parish Signed-off-by: [email protected]
xen/include/asm-x86/e820.h +13 -0
@@ -36,4 +36,17 @@ extern void print_e820_memory_map(struct#define PFN_DOWN (x) ((x) >> PAGE_SHIFT)#define PFN_UP (x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT) +static inline int pfn_valid (unsigned long pfn) { +int i; + +for (i =0 ; i < e820.nr_map; i++) { +if (pfn >= (e820.map[i].addr >>PAGE_SHIFT ) && + pfn < ((e820.map[i].addr & ~PAGE_MASK ) + + e820.map[i].size) >>PAGE_SHIFT ) +return 1 ; + } + +return 0 ; +} +#endif /*__E820_HEADER*/
xen/include/asm-x86/page.h +0 -1
@@ -36,7 +36,6 @@ typedef struct { unsigned long pt_lo; }#define pfn_to_page (_pfn) (frame_table + (_pfn))#define phys_to_page (kaddr) (frame_table + ((kaddr) >> PAGE_SHIFT))#define virt_to_page (kaddr) (frame_table + (__pa(kaddr) >> PAGE_SHIFT)) -#define pfn_valid (_pfn) ((_pfn) < max_page)/* High table entries are reserved by the hypervisor. */ #define DOMAIN_ENTRIES_PER_L2_PAGETABLE \
_______________________________________________
Xen-devel mailing list
[email protected]
http://lists.xensource.com/xen-devel