[PATCH] x86: fix virt_addr_valid() with CONFIG_DEBUG_VIRTUAL=y

From: Vegard Nossum
Date: Fri Oct 03 2008 - 09:58:50 EST


virt_addr_valid() calls __pa(), which calls __phys_addr(). With
CONFIG_DEBUG_VIRTUAL=y, __phys_addr() will kill the kernel if the
address *isn't* valid. That's clearly wrong for virt_addr_valid().

Cc: Jiri Slaby <jirislaby@xxxxxxxxx>
Cc: Andi Kleen <andi@xxxxxxxxxxxxxx>
Signed-off-by: Vegard Nossum <vegardno@xxxxxxxxxxxxxx>
---
arch/x86/kernel/doublefault_32.c | 2 +-
arch/x86/mm/ioremap.c | 12 ++++++++++++
include/asm-x86/page.h | 3 ++-
include/asm-x86/page_32.h | 4 ++--
include/asm-x86/page_64.h | 1 +
5 files changed, 18 insertions(+), 4 deletions(-)

diff --git a/arch/x86/kernel/doublefault_32.c b/arch/x86/kernel/doublefault_32.c
index 395acb1..b4f14c6 100644
--- a/arch/x86/kernel/doublefault_32.c
+++ b/arch/x86/kernel/doublefault_32.c
@@ -66,6 +66,6 @@ struct tss_struct doublefault_tss __cacheline_aligned = {
.ds = __USER_DS,
.fs = __KERNEL_PERCPU,

- .__cr3 = __phys_addr_const((unsigned long)swapper_pg_dir)
+ .__cr3 = __pa_nodebug(swapper_pg_dir),
}
};
diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c
index 835e062..2d5e6de 100644
--- a/arch/x86/mm/ioremap.c
+++ b/arch/x86/mm/ioremap.c
@@ -29,6 +29,18 @@ static inline int phys_addr_valid(unsigned long addr)
return addr < (1UL << boot_cpu_data.x86_phys_bits);
}

+unsigned long __phys_addr_nodebug(unsigned long x)
+{
+ if (x >= __START_KERNEL_map) {
+ x -= __START_KERNEL_map;
+ x += phys_base;
+ } else {
+ x -= PAGE_OFFSET;
+ }
+
+ return x;
+}
+
unsigned long __phys_addr(unsigned long x)
{
if (x >= __START_KERNEL_map) {
diff --git a/include/asm-x86/page.h b/include/asm-x86/page.h
index c915747..9b70b41 100644
--- a/include/asm-x86/page.h
+++ b/include/asm-x86/page.h
@@ -179,6 +179,7 @@ static inline pteval_t native_pte_flags(pte_t pte)
#endif /* CONFIG_PARAVIRT */

#define __pa(x) __phys_addr((unsigned long)(x))
+#define __pa_nodebug(x) __phys_addr_nodebug((unsigned long)(x))
/* __pa_symbol should be used for C visible symbols.
This seems to be the official gcc blessed way to do such arithmetic. */
#define __pa_symbol(x) __pa(__phys_reloc_hide((unsigned long)(x)))
@@ -190,7 +191,7 @@ static inline pteval_t native_pte_flags(pte_t pte)

#define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
#define pfn_to_kaddr(pfn) __va((pfn) << PAGE_SHIFT)
-#define virt_addr_valid(kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT)
+#define virt_addr_valid(kaddr) pfn_valid(__pa_nodebug(kaddr) >> PAGE_SHIFT)

#endif /* __ASSEMBLY__ */

diff --git a/include/asm-x86/page_32.h b/include/asm-x86/page_32.h
index 82b0109..deec501 100644
--- a/include/asm-x86/page_32.h
+++ b/include/asm-x86/page_32.h
@@ -71,11 +71,11 @@ typedef struct page *pgtable_t;
#endif

#ifndef __ASSEMBLY__
-#define __phys_addr_const(x) ((x) - PAGE_OFFSET)
+#define __phys_addr_nodebug(x) ((x) - PAGE_OFFSET)
#ifdef CONFIG_DEBUG_VIRTUAL
extern unsigned long __phys_addr(unsigned long);
#else
-#define __phys_addr(x) ((x) - PAGE_OFFSET)
+#define __phys_addr(x) __phys_addr_nodebug(x)
#endif
#define __phys_reloc_hide(x) RELOC_HIDE((x), 0)

diff --git a/include/asm-x86/page_64.h b/include/asm-x86/page_64.h
index 49380b8..d2a851e 100644
--- a/include/asm-x86/page_64.h
+++ b/include/asm-x86/page_64.h
@@ -68,6 +68,7 @@ void copy_page(void *to, void *from);
extern unsigned long max_pfn;
extern unsigned long phys_base;

+extern unsigned long __phys_addr_nodebug(unsigned long);
extern unsigned long __phys_addr(unsigned long);
#define __phys_reloc_hide(x) (x)

--
1.5.5.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/