Hi,
Yamahata-san is right. After more investigation, that page is valid
but the page struct is missing.
Attached patch fixes this issue but I think this patch is messy.
Probably it's a stopgap until P2M/VP integration.
Signed-off-by: Kouya Shimura <kouya@xxxxxxxxxxxxxx>
Thanks,
Kouya
Isaku Yamahata writes:
>
> On Tue, Apr 18, 2006 at 07:41:55PM +0900, Kouya SHIMURA wrote:
> Content-Description: message body text
>
> > We encounter a Oops message from loop driver when vbd is used
> > in dom0 kernel with CONFIG_VIRTUAL_MEM_MAP on ia64.
> >
> > I investigated this and might find a serious bug.
> > On x86, flush_dcache_page() does nothing and there is no problem.
> > But on ia64 flush_dcache_page() might access a wrong page struct
> > and destroy the kernel memory.
> >
> > Attached patch fixes this problem but it seems bad idea to modify
> > a linux driver. How should we fix it?
>
> Why is a invalid page passed?
> Should it be fixed instead of modifying loop.c?
>
> --
> yamahata
diff -r 7ed6c203efe9 linux-2.6-xen-sparse/arch/ia64/xen/drivers/xenia64_init.c
--- a/linux-2.6-xen-sparse/arch/ia64/xen/drivers/xenia64_init.c Wed Apr 19
10:39:15 2006 -0600
+++ b/linux-2.6-xen-sparse/arch/ia64/xen/drivers/xenia64_init.c Thu Apr 20
20:37:20 2006 +0900
@@ -43,7 +43,7 @@ unsigned long alloc_empty_foreign_map_pa
struct vm_struct *vma;
if ( (vma = get_vm_area(PAGE_SIZE * pages, VM_ALLOC)) == NULL )
- return NULL;
+ return 0;
return (unsigned long)vma->addr;
}
@@ -53,4 +53,55 @@ unsigned long alloc_empty_foreign_map_pa
* a convenient arch include */
unsigned long mfn_to_pfn(unsigned long mfn) { return mfn; }
#endif
+
+#ifdef CONFIG_VIRTUAL_MEM_MAP
+#include <asm/pgalloc.h>
+#include <asm/meminit.h>
+
+static inline void *alloc_one_page(void)
+{
+ struct page *pg = alloc_page(GFP_KERNEL);
+ unsigned long pfn;
+ void *p;
+
+ if (!pg)
+ panic("Not enough memory for virtual mem map!\n");
+ pfn = page_to_pfn(pg);
+ p = (void *)(pfn << PAGE_SHIFT);
+ memset(__va(p), 0, PAGE_SIZE);
+ return p;
+}
+
+void
+extend_mem_map_page_table (u64 vaddr)
+{
+ unsigned long address;
+ struct page *map;
+ pgd_t *pgd;
+ pud_t *pud;
+ pmd_t *pmd;
+ pte_t *pte;
+
+ map = vmem_map + (__pa(vaddr) >> PAGE_SHIFT);
+ address = (unsigned long) map & PAGE_MASK;
+
+ pgd = pgd_offset_k(address);
+ if (pgd_none(*pgd))
+ pgd_populate(&init_mm, pgd, alloc_one_page());
+ pud = pud_offset(pgd, address);
+
+ if (pud_none(*pud))
+ pud_populate(&init_mm, pud, alloc_one_page());
+ pmd = pmd_offset(pud, address);
+
+ if (pmd_none(*pmd))
+ pmd_populate_kernel(&init_mm, pmd, alloc_one_page());
+ pte = pte_offset_kernel(pmd, address);
+
+ if (pte_none(*pte))
+ set_pte(pte, pfn_pte(__pa(alloc_one_page()) >> PAGE_SHIFT,
+ PAGE_KERNEL));
+}
+#endif /* CONFIG_VIRTUAL_MEM_MAP */
+
#endif
diff -r 7ed6c203efe9 linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c
--- a/linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c Wed Apr 19
10:39:15 2006 -0600
+++ b/linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c Thu Apr 20
20:37:20 2006 +0900
@@ -413,6 +413,15 @@ static void dispatch_rw_block_io(blkif_t
#ifdef __ia64__
pending_vaddrs[vaddr_pagenr(pending_req, i)] =
(unsigned long)gnttab_map_vaddr(map[i]);
+#ifdef CONFIG_VIRTUAL_MEM_MAP
+ {
+ extern void extend_mem_map_page_table(u64);
+ u64 vaddr = gnttab_map_vaddr(map[i]);
+
+ if (!pfn_valid(__pa(vaddr) >> PAGE_SHIFT))
+ extend_mem_map_page_table(vaddr);
+ }
+#endif
#else
set_phys_to_machine(__pa(vaddr(
pending_req, i)) >> PAGE_SHIFT,
_______________________________________________
Xen-ia64-devel mailing list
Xen-ia64-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-ia64-devel
|