Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0-only */
0002 /*
0003  *  arch/arm/include/asm/proc-fns.h
0004  *
0005  *  Copyright (C) 1997-1999 Russell King
0006  *  Copyright (C) 2000 Deep Blue Solutions Ltd
0007  */
0008 #ifndef __ASM_PROCFNS_H
0009 #define __ASM_PROCFNS_H
0010 
0011 #ifdef __KERNEL__
0012 
0013 #include <asm/glue-proc.h>
0014 #include <asm/page.h>
0015 
0016 #ifndef __ASSEMBLY__
0017 
0018 struct mm_struct;
0019 
0020 /*
0021  * Don't change this structure - ASM code relies on it.
0022  */
0023 struct processor {
0024     /* MISC
0025      * get data abort address/flags
0026      */
0027     void (*_data_abort)(unsigned long pc);
0028     /*
0029      * Retrieve prefetch fault address
0030      */
0031     unsigned long (*_prefetch_abort)(unsigned long lr);
0032     /*
0033      * Set up any processor specifics
0034      */
0035     void (*_proc_init)(void);
0036     /*
0037      * Check for processor bugs
0038      */
0039     void (*check_bugs)(void);
0040     /*
0041      * Disable any processor specifics
0042      */
0043     void (*_proc_fin)(void);
0044     /*
0045      * Special stuff for a reset
0046      */
0047     void (*reset)(unsigned long addr, bool hvc) __attribute__((noreturn));
0048     /*
0049      * Idle the processor
0050      */
0051     int (*_do_idle)(void);
0052     /*
0053      * Processor architecture specific
0054      */
0055     /*
0056      * clean a virtual address range from the
0057      * D-cache without flushing the cache.
0058      */
0059     void (*dcache_clean_area)(void *addr, int size);
0060 
0061     /*
0062      * Set the page table
0063      */
0064     void (*switch_mm)(phys_addr_t pgd_phys, struct mm_struct *mm);
0065     /*
0066      * Set a possibly extended PTE.  Non-extended PTEs should
0067      * ignore 'ext'.
0068      */
0069 #ifdef CONFIG_ARM_LPAE
0070     void (*set_pte_ext)(pte_t *ptep, pte_t pte);
0071 #else
0072     void (*set_pte_ext)(pte_t *ptep, pte_t pte, unsigned int ext);
0073 #endif
0074 
0075     /* Suspend/resume */
0076     unsigned int suspend_size;
0077     void (*do_suspend)(void *);
0078     void (*do_resume)(void *);
0079 };
0080 
0081 #ifndef MULTI_CPU
0082 static inline void init_proc_vtable(const struct processor *p)
0083 {
0084 }
0085 
0086 extern void cpu_proc_init(void);
0087 extern void cpu_proc_fin(void);
0088 extern int cpu_do_idle(void);
0089 extern void cpu_dcache_clean_area(void *, int);
0090 extern void cpu_do_switch_mm(phys_addr_t pgd_phys, struct mm_struct *mm);
0091 #ifdef CONFIG_ARM_LPAE
0092 extern void cpu_set_pte_ext(pte_t *ptep, pte_t pte);
0093 #else
0094 extern void cpu_set_pte_ext(pte_t *ptep, pte_t pte, unsigned int ext);
0095 #endif
0096 extern void cpu_reset(unsigned long addr, bool hvc) __attribute__((noreturn));
0097 
0098 /* These three are private to arch/arm/kernel/suspend.c */
0099 extern void cpu_do_suspend(void *);
0100 extern void cpu_do_resume(void *);
0101 #else
0102 
0103 extern struct processor processor;
0104 #if defined(CONFIG_BIG_LITTLE) && defined(CONFIG_HARDEN_BRANCH_PREDICTOR)
0105 #include <linux/smp.h>
0106 /*
0107  * This can't be a per-cpu variable because we need to access it before
0108  * per-cpu has been initialised.  We have a couple of functions that are
0109  * called in a pre-emptible context, and so can't use smp_processor_id()
0110  * there, hence PROC_TABLE().  We insist in init_proc_vtable() that the
0111  * function pointers for these are identical across all CPUs.
0112  */
0113 extern struct processor *cpu_vtable[];
0114 #define PROC_VTABLE(f)          cpu_vtable[smp_processor_id()]->f
0115 #define PROC_TABLE(f)           cpu_vtable[0]->f
0116 static inline void init_proc_vtable(const struct processor *p)
0117 {
0118     unsigned int cpu = smp_processor_id();
0119     *cpu_vtable[cpu] = *p;
0120     WARN_ON_ONCE(cpu_vtable[cpu]->dcache_clean_area !=
0121              cpu_vtable[0]->dcache_clean_area);
0122     WARN_ON_ONCE(cpu_vtable[cpu]->set_pte_ext !=
0123              cpu_vtable[0]->set_pte_ext);
0124 }
0125 #else
0126 #define PROC_VTABLE(f)          processor.f
0127 #define PROC_TABLE(f)           processor.f
0128 static inline void init_proc_vtable(const struct processor *p)
0129 {
0130     processor = *p;
0131 }
0132 #endif
0133 
0134 #define cpu_proc_init           PROC_VTABLE(_proc_init)
0135 #define cpu_check_bugs          PROC_VTABLE(check_bugs)
0136 #define cpu_proc_fin            PROC_VTABLE(_proc_fin)
0137 #define cpu_reset           PROC_VTABLE(reset)
0138 #define cpu_do_idle         PROC_VTABLE(_do_idle)
0139 #define cpu_dcache_clean_area       PROC_TABLE(dcache_clean_area)
0140 #define cpu_set_pte_ext         PROC_TABLE(set_pte_ext)
0141 #define cpu_do_switch_mm        PROC_VTABLE(switch_mm)
0142 
0143 /* These two are private to arch/arm/kernel/suspend.c */
0144 #define cpu_do_suspend          PROC_VTABLE(do_suspend)
0145 #define cpu_do_resume           PROC_VTABLE(do_resume)
0146 #endif
0147 
0148 extern void cpu_resume(void);
0149 
0150 #include <asm/memory.h>
0151 
0152 #ifdef CONFIG_MMU
0153 
0154 #define cpu_switch_mm(pgd,mm) cpu_do_switch_mm(virt_to_phys(pgd),mm)
0155 
0156 #ifdef CONFIG_ARM_LPAE
0157 
0158 #define cpu_get_ttbr(nr)                    \
0159     ({                          \
0160         u64 ttbr;                   \
0161         __asm__("mrrc   p15, " #nr ", %Q0, %R0, c2" \
0162             : "=r" (ttbr));             \
0163         ttbr;                       \
0164     })
0165 
0166 #define cpu_get_pgd()   \
0167     ({                      \
0168         u64 pg = cpu_get_ttbr(0);       \
0169         pg &= ~(PTRS_PER_PGD*sizeof(pgd_t)-1);  \
0170         (pgd_t *)phys_to_virt(pg);      \
0171     })
0172 #else
0173 #define cpu_get_pgd()   \
0174     ({                      \
0175         unsigned long pg;           \
0176         __asm__("mrc    p15, 0, %0, c2, c0, 0"  \
0177              : "=r" (pg) : : "cc");     \
0178         pg &= ~0x3fff;              \
0179         (pgd_t *)phys_to_virt(pg);      \
0180     })
0181 #endif
0182 
0183 #else   /*!CONFIG_MMU */
0184 
0185 #define cpu_switch_mm(pgd,mm)   { }
0186 
0187 #endif
0188 
0189 #endif /* __ASSEMBLY__ */
0190 #endif /* __KERNEL__ */
0191 #endif /* __ASM_PROCFNS_H */