Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * arch/arm/kernel/thumbee.c
0004  *
0005  * Copyright (C) 2008 ARM Limited
0006  */
0007 
0008 #include <linux/kernel.h>
0009 #include <linux/init.h>
0010 
0011 #include <asm/cputype.h>
0012 #include <asm/system_info.h>
0013 #include <asm/thread_notify.h>
0014 
0015 /*
0016  * Access to the ThumbEE Handler Base register
0017  */
0018 static inline unsigned long teehbr_read(void)
0019 {
0020     unsigned long v;
0021     asm("mrc    p14, 6, %0, c1, c0, 0\n" : "=r" (v));
0022     return v;
0023 }
0024 
0025 static inline void teehbr_write(unsigned long v)
0026 {
0027     asm("mcr    p14, 6, %0, c1, c0, 0\n" : : "r" (v));
0028 }
0029 
0030 static int thumbee_notifier(struct notifier_block *self, unsigned long cmd, void *t)
0031 {
0032     struct thread_info *thread = t;
0033 
0034     switch (cmd) {
0035     case THREAD_NOTIFY_FLUSH:
0036         teehbr_write(0);
0037         break;
0038     case THREAD_NOTIFY_SWITCH:
0039         current_thread_info()->thumbee_state = teehbr_read();
0040         teehbr_write(thread->thumbee_state);
0041         break;
0042     }
0043 
0044     return NOTIFY_DONE;
0045 }
0046 
0047 static struct notifier_block thumbee_notifier_block = {
0048     .notifier_call  = thumbee_notifier,
0049 };
0050 
0051 static int __init thumbee_init(void)
0052 {
0053     unsigned long pfr0;
0054     unsigned int cpu_arch = cpu_architecture();
0055 
0056     if (cpu_arch < CPU_ARCH_ARMv7)
0057         return 0;
0058 
0059     pfr0 = read_cpuid_ext(CPUID_EXT_PFR0);
0060     if ((pfr0 & 0x0000f000) != 0x00001000)
0061         return 0;
0062 
0063     pr_info("ThumbEE CPU extension supported.\n");
0064     elf_hwcap |= HWCAP_THUMBEE;
0065     thread_register_notifier(&thumbee_notifier_block);
0066 
0067     return 0;
0068 }
0069 
0070 late_initcall(thumbee_init);