When Chris and I were debugging x86_64 SMP xenlinux, I noticed that
(include/asm-x86/mm.h):
#if defined(__i386__)
#define pickle_domptr(_d) ((u32)(unsigned long)(_d))
#define unpickle_domptr(_d) ((struct domain *)(unsigned long)(_d))
#elif defined(__x86_64__)
static inline struct domain *unpickle_domptr(u32 _domain)
{ return (_domain == 0) ? NULL : __va(_domain); }
static inline u32 pickle_domptr(struct domain *domain)
{ return (domain == NULL) ? 0 : (u32)__pa(domain); }
#endif
__pa(domain) will be truncated (and be set to that pfn as the owner)
when we have physical pages >4GB, and unpickle_domptr will return a
wrong address. Then get_page(), for example, checks if the domain is the
ownwer for the page like (=>), and it fails...:
static inline int get_page(struct pfn_info *page,
struct domain *domain)
{
u32 x, nx, y = page->count_info;
u32 d, nd = page->u.inuse._domain;
u32 _domain = pickle_domptr(domain);
do {
x = y;
nx = x + 1;
d = nd;
if ( unlikely((x & PGC_count_mask) == 0) || /* Not allocated?
*/
unlikely((nx & PGC_count_mask) == 0) || /* Count overflow?
*/
=> unlikely(d != _domain) ) /* Wrong owner? */
{
if ( !_shadow_mode_refcounts(domain) )
DPRINTK("Error pfn %lx: rd=%p, od=%p, caf=%08x,
taf=%08x\n",
page_to_pfn(page), domain, unpickle_domptr(d),
x, page->u.inuse.type_info);
return 0;
}
Jun
---
Intel Open Source Technology Center
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
|