[PATCH 1/4] ARM: Remove the domain switching on ARMv6k/v7 CPUs
Catalin Marinas
catalin.marinas at arm.com
Mon May 24 09:52:52 EDT 2010
On Mon, 2010-05-24 at 14:25 +0100, Catalin Marinas wrote:
> On Mon, 2010-05-24 at 12:45 +0100, Russell King - ARM Linux wrote:
> > On Thu, May 20, 2010 at 03:30:04PM +0100, Catalin Marinas wrote:
> > > The user pages access rights are also modified for kernel read-only
> > > access rather than read/write so that the copy-on-write mechanism still
> > > works. CPU_USE_DOMAINS gets disabled only if HAS_TLS_REG is defined
> > > since writing the TLS value to the high vectors page isn't possible.
> >
> > When FIQ handlers are installed/removed, the vector page is also written,
> > so the above restriction is incompatible with FIQ support.
> >
> > Do we want to tell people that they can't use FIQs without domain support?
>
> They could still be used (with an additional patch). At first, I thought
> that we could do something similar to early_trap_init() but
> set_fiq_handler() could be called from a module at run-time and it may
> temporarily enable write access to the vectors page (without an
> additional L_PTE_ bit we can't make the vectors page user RO, kernel R/W
> and I wouldn't do this anyway, for other reasons).
>
> What about making a global vectors_page variable (initialised in
> devicemaps_init) that can be written directly when !CPU_USE_DOMAINS? On
> such CPUs, we have a non-aliasing VIPT cache anyway.
That's the additional diff which allows FIQs when !CPU_USE_DOMAINS
(assuming VIPT non-aliasing caches). I also modified the
early_trap_init() to make use of the vectors page rather than setting
the PTE as in the original patch.
diff --git a/arch/arm/include/asm/traps.h b/arch/arm/include/asm/traps.h
index 491960b..af5d5d1 100644
--- a/arch/arm/include/asm/traps.h
+++ b/arch/arm/include/asm/traps.h
@@ -27,4 +27,6 @@ static inline int in_exception_text(unsigned long ptr)
extern void __init early_trap_init(void);
extern void dump_backtrace_entry(unsigned long where, unsigned long from, unsigned long frame);
+extern void *vectors_page;
+
#endif
diff --git a/arch/arm/kernel/fiq.c b/arch/arm/kernel/fiq.c
index 6ff7919..fb1a640 100644
--- a/arch/arm/kernel/fiq.c
+++ b/arch/arm/kernel/fiq.c
@@ -45,6 +45,7 @@
#include <asm/fiq.h>
#include <asm/irq.h>
#include <asm/system.h>
+#include <asm/traps.h>
static unsigned long no_fiq_insn;
@@ -77,7 +78,11 @@ int show_fiq_list(struct seq_file *p, void *v)
void set_fiq_handler(void *start, unsigned int length)
{
+#if defined(CONFIG_CPU_USE_DOMAINS)
memcpy((void *)0xffff001c, start, length);
+#else
+ memcpy(vectors_page + 0x1c, start, length);
+#endif
flush_icache_range(0xffff001c, 0xffff001c + length);
if (!vectors_high())
flush_icache_range(0x1c, 0x1c + length);
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
index 6571e19..6bc57c5 100644
--- a/arch/arm/kernel/traps.c
+++ b/arch/arm/kernel/traps.c
@@ -30,13 +30,14 @@
#include <asm/unistd.h>
#include <asm/traps.h>
#include <asm/unwind.h>
-#include <asm/tlbflush.h>
#include "ptrace.h"
#include "signal.h"
static const char *handler[]= { "prefetch abort", "data abort", "address exception", "interrupt" };
+void *vectors_page;
+
#ifdef CONFIG_DEBUG_USER
unsigned int user_debug;
@@ -746,21 +747,15 @@ void __init trap_init(void)
void __init early_trap_init(void)
{
+#if defined(CONFIG_CPU_USE_DOMAINS)
unsigned long vectors = CONFIG_VECTORS_BASE;
+#else
+ unsigned long vectors = (unsigned long)vectors_page;
+#endif
extern char __stubs_start[], __stubs_end[];
extern char __vectors_start[], __vectors_end[];
extern char __kuser_helper_start[], __kuser_helper_end[];
int kuser_sz = __kuser_helper_end - __kuser_helper_start;
-#if !defined(CONFIG_CPU_USE_DOMAINS) && defined(CONFIG_MMU)
- pgd_t *pgd = pgd_offset_k(vectors);
- pmd_t *pmd = pmd_offset(pgd, vectors);
- pte_t *pte = pte_offset_kernel(pmd, vectors);
- pte_t entry = *pte;
-
- /* allow writing to the vectors page */
- set_pte_ext(pte, pte_mkwrite(entry), 0);
- local_flush_tlb_kernel_page(vectors);
-#endif
/*
* Copy the vectors, stubs and kuser helpers (in entry-armv.S)
@@ -775,16 +770,10 @@ void __init early_trap_init(void)
* Copy signal return handlers into the vector page, and
* set sigreturn to be a pointer to these.
*/
- memcpy((void *)KERN_SIGRETURN_CODE, sigreturn_codes,
- sizeof(sigreturn_codes));
- memcpy((void *)KERN_RESTART_CODE, syscall_restart_code,
- sizeof(syscall_restart_code));
-
-#if !defined(CONFIG_CPU_USE_DOMAINS) && defined(CONFIG_MMU)
- /* restore the vectors page permissions */
- set_pte_ext(pte, entry, 0);
- local_flush_tlb_kernel_page(vectors);
-#endif
+ memcpy((void *)(vectors + KERN_SIGRETURN_CODE - CONFIG_VECTORS_BASE),
+ sigreturn_codes, sizeof(sigreturn_codes));
+ memcpy((void *)(vectors + KERN_RESTART_CODE - CONFIG_VECTORS_BASE),
+ syscall_restart_code, sizeof(syscall_restart_code));
flush_icache_range(vectors, vectors + PAGE_SIZE);
modify_domain(DOMAIN_USER, DOMAIN_CLIENT);
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index 2858941..499e22d 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -25,6 +25,7 @@
#include <asm/smp_plat.h>
#include <asm/tlb.h>
#include <asm/highmem.h>
+#include <asm/traps.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
@@ -935,12 +936,11 @@ static void __init devicemaps_init(struct machine_desc *mdesc)
{
struct map_desc map;
unsigned long addr;
- void *vectors;
/*
* Allocate the vector page early.
*/
- vectors = alloc_bootmem_low_pages(PAGE_SIZE);
+ vectors_page = alloc_bootmem_low_pages(PAGE_SIZE);
for (addr = VMALLOC_END; addr; addr += PGDIR_SIZE)
pmd_clear(pmd_off_k(addr));
@@ -980,7 +980,7 @@ static void __init devicemaps_init(struct machine_desc *mdesc)
* location (0xffff0000). If we aren't using high-vectors, also
* create a mapping at the low-vectors virtual address.
*/
- map.pfn = __phys_to_pfn(virt_to_phys(vectors));
+ map.pfn = __phys_to_pfn(virt_to_phys(vectors_page));
map.virtual = 0xffff0000;
map.length = PAGE_SIZE;
map.type = MT_HIGH_VECTORS;
--
Catalin
More information about the linux-arm-kernel
mailing list