thumbee.c (1402B)
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * arch/arm/kernel/thumbee.c 4 * 5 * Copyright (C) 2008 ARM Limited 6 */ 7 8#include <linux/kernel.h> 9#include <linux/init.h> 10 11#include <asm/cputype.h> 12#include <asm/system_info.h> 13#include <asm/thread_notify.h> 14 15/* 16 * Access to the ThumbEE Handler Base register 17 */ 18static inline unsigned long teehbr_read(void) 19{ 20 unsigned long v; 21 asm("mrc p14, 6, %0, c1, c0, 0\n" : "=r" (v)); 22 return v; 23} 24 25static inline void teehbr_write(unsigned long v) 26{ 27 asm("mcr p14, 6, %0, c1, c0, 0\n" : : "r" (v)); 28} 29 30static int thumbee_notifier(struct notifier_block *self, unsigned long cmd, void *t) 31{ 32 struct thread_info *thread = t; 33 34 switch (cmd) { 35 case THREAD_NOTIFY_FLUSH: 36 teehbr_write(0); 37 break; 38 case THREAD_NOTIFY_SWITCH: 39 current_thread_info()->thumbee_state = teehbr_read(); 40 teehbr_write(thread->thumbee_state); 41 break; 42 } 43 44 return NOTIFY_DONE; 45} 46 47static struct notifier_block thumbee_notifier_block = { 48 .notifier_call = thumbee_notifier, 49}; 50 51static int __init thumbee_init(void) 52{ 53 unsigned long pfr0; 54 unsigned int cpu_arch = cpu_architecture(); 55 56 if (cpu_arch < CPU_ARCH_ARMv7) 57 return 0; 58 59 pfr0 = read_cpuid_ext(CPUID_EXT_PFR0); 60 if ((pfr0 & 0x0000f000) != 0x00001000) 61 return 0; 62 63 pr_info("ThumbEE CPU extension supported.\n"); 64 elf_hwcap |= HWCAP_THUMBEE; 65 thread_register_notifier(&thumbee_notifier_block); 66 67 return 0; 68} 69 70late_initcall(thumbee_init);