1*d2912cb1SThomas Gleixner /* SPDX-License-Identifier: GPL-2.0-only */
24baa9922SRussell King /*
34baa9922SRussell King * arch/arm/include/asm/proc-fns.h
44baa9922SRussell King *
54baa9922SRussell King * Copyright (C) 1997-1999 Russell King
64baa9922SRussell King * Copyright (C) 2000 Deep Blue Solutions Ltd
74baa9922SRussell King */
84baa9922SRussell King #ifndef __ASM_PROCFNS_H
94baa9922SRussell King #define __ASM_PROCFNS_H
104baa9922SRussell King
114baa9922SRussell King #ifdef __KERNEL__
124baa9922SRussell King
13753790e7SRussell King #include <asm/glue-proc.h>
14753790e7SRussell King #include <asm/page.h>
154baa9922SRussell King
164baa9922SRussell King #ifndef __ASSEMBLY__
174baa9922SRussell King
18753790e7SRussell King struct mm_struct;
19753790e7SRussell King
20753790e7SRussell King /*
21753790e7SRussell King * Don't change this structure - ASM code relies on it.
22753790e7SRussell King */
23e209950fSRussell King struct processor {
24753790e7SRussell King /* MISC
25753790e7SRussell King * get data abort address/flags
26753790e7SRussell King */
27753790e7SRussell King void (*_data_abort)(unsigned long pc);
28753790e7SRussell King /*
29753790e7SRussell King * Retrieve prefetch fault address
30753790e7SRussell King */
31753790e7SRussell King unsigned long (*_prefetch_abort)(unsigned long lr);
32753790e7SRussell King /*
33753790e7SRussell King * Set up any processor specifics
34753790e7SRussell King */
35753790e7SRussell King void (*_proc_init)(void);
36753790e7SRussell King /*
379d3a0492SRussell King * Check for processor bugs
389d3a0492SRussell King */
399d3a0492SRussell King void (*check_bugs)(void);
409d3a0492SRussell King /*
41753790e7SRussell King * Disable any processor specifics
42753790e7SRussell King */
43753790e7SRussell King void (*_proc_fin)(void);
44753790e7SRussell King /*
45753790e7SRussell King * Special stuff for a reset
46753790e7SRussell King */
479da5ac23SRussell King void (*reset)(unsigned long addr, bool hvc) __attribute__((noreturn));
48753790e7SRussell King /*
49753790e7SRussell King * Idle the processor
50753790e7SRussell King */
51753790e7SRussell King int (*_do_idle)(void);
52753790e7SRussell King /*
53753790e7SRussell King * Processor architecture specific
54753790e7SRussell King */
55753790e7SRussell King /*
56753790e7SRussell King * clean a virtual address range from the
57753790e7SRussell King * D-cache without flushing the cache.
58753790e7SRussell King */
59753790e7SRussell King void (*dcache_clean_area)(void *addr, int size);
60753790e7SRussell King
61753790e7SRussell King /*
62753790e7SRussell King * Set the page table
63753790e7SRussell King */
6413f659b0SCyril Chemparathy void (*switch_mm)(phys_addr_t pgd_phys, struct mm_struct *mm);
65753790e7SRussell King /*
66753790e7SRussell King * Set a possibly extended PTE. Non-extended PTEs should
67753790e7SRussell King * ignore 'ext'.
68753790e7SRussell King */
69da028779SCatalin Marinas #ifdef CONFIG_ARM_LPAE
70da028779SCatalin Marinas void (*set_pte_ext)(pte_t *ptep, pte_t pte);
71da028779SCatalin Marinas #else
72753790e7SRussell King void (*set_pte_ext)(pte_t *ptep, pte_t pte, unsigned int ext);
73da028779SCatalin Marinas #endif
74f6b0fa02SRussell King
75f6b0fa02SRussell King /* Suspend/resume */
76f6b0fa02SRussell King unsigned int suspend_size;
77f6b0fa02SRussell King void (*do_suspend)(void *);
78f6b0fa02SRussell King void (*do_resume)(void *);
79e209950fSRussell King };
80753790e7SRussell King
814baa9922SRussell King #ifndef MULTI_CPU
init_proc_vtable(const struct processor * p)82e209950fSRussell King static inline void init_proc_vtable(const struct processor *p)
83e209950fSRussell King {
84e209950fSRussell King }
85e209950fSRussell King
86753790e7SRussell King extern void cpu_proc_init(void);
87753790e7SRussell King extern void cpu_proc_fin(void);
88753790e7SRussell King extern int cpu_do_idle(void);
89753790e7SRussell King extern void cpu_dcache_clean_area(void *, int);
9013f659b0SCyril Chemparathy extern void cpu_do_switch_mm(phys_addr_t pgd_phys, struct mm_struct *mm);
91da028779SCatalin Marinas #ifdef CONFIG_ARM_LPAE
92da028779SCatalin Marinas extern void cpu_set_pte_ext(pte_t *ptep, pte_t pte);
93da028779SCatalin Marinas #else
94753790e7SRussell King extern void cpu_set_pte_ext(pte_t *ptep, pte_t pte, unsigned int ext);
95da028779SCatalin Marinas #endif
969da5ac23SRussell King extern void cpu_reset(unsigned long addr, bool hvc) __attribute__((noreturn));
97abda1bd5SRussell King
98abda1bd5SRussell King /* These three are private to arch/arm/kernel/suspend.c */
99abda1bd5SRussell King extern void cpu_do_suspend(void *);
100abda1bd5SRussell King extern void cpu_do_resume(void *);
1014baa9922SRussell King #else
102abda1bd5SRussell King
103e209950fSRussell King extern struct processor processor;
104383fb3eeSRussell King #if defined(CONFIG_BIG_LITTLE) && defined(CONFIG_HARDEN_BRANCH_PREDICTOR)
105383fb3eeSRussell King #include <linux/smp.h>
106383fb3eeSRussell King /*
107383fb3eeSRussell King * This can't be a per-cpu variable because we need to access it before
108383fb3eeSRussell King * per-cpu has been initialised. We have a couple of functions that are
109383fb3eeSRussell King * called in a pre-emptible context, and so can't use smp_processor_id()
110383fb3eeSRussell King * there, hence PROC_TABLE(). We insist in init_proc_vtable() that the
111383fb3eeSRussell King * function pointers for these are identical across all CPUs.
112383fb3eeSRussell King */
113383fb3eeSRussell King extern struct processor *cpu_vtable[];
114383fb3eeSRussell King #define PROC_VTABLE(f) cpu_vtable[smp_processor_id()]->f
115383fb3eeSRussell King #define PROC_TABLE(f) cpu_vtable[0]->f
init_proc_vtable(const struct processor * p)116383fb3eeSRussell King static inline void init_proc_vtable(const struct processor *p)
117383fb3eeSRussell King {
118383fb3eeSRussell King unsigned int cpu = smp_processor_id();
119383fb3eeSRussell King *cpu_vtable[cpu] = *p;
120383fb3eeSRussell King WARN_ON_ONCE(cpu_vtable[cpu]->dcache_clean_area !=
121383fb3eeSRussell King cpu_vtable[0]->dcache_clean_area);
122383fb3eeSRussell King WARN_ON_ONCE(cpu_vtable[cpu]->set_pte_ext !=
123383fb3eeSRussell King cpu_vtable[0]->set_pte_ext);
124383fb3eeSRussell King }
125383fb3eeSRussell King #else
126e209950fSRussell King #define PROC_VTABLE(f) processor.f
127e209950fSRussell King #define PROC_TABLE(f) processor.f
init_proc_vtable(const struct processor * p)128e209950fSRussell King static inline void init_proc_vtable(const struct processor *p)
129e209950fSRussell King {
130e209950fSRussell King processor = *p;
131e209950fSRussell King }
132383fb3eeSRussell King #endif
133e209950fSRussell King
134e209950fSRussell King #define cpu_proc_init PROC_VTABLE(_proc_init)
135e209950fSRussell King #define cpu_check_bugs PROC_VTABLE(check_bugs)
136e209950fSRussell King #define cpu_proc_fin PROC_VTABLE(_proc_fin)
137e209950fSRussell King #define cpu_reset PROC_VTABLE(reset)
138e209950fSRussell King #define cpu_do_idle PROC_VTABLE(_do_idle)
139e209950fSRussell King #define cpu_dcache_clean_area PROC_TABLE(dcache_clean_area)
140e209950fSRussell King #define cpu_set_pte_ext PROC_TABLE(set_pte_ext)
141e209950fSRussell King #define cpu_do_switch_mm PROC_VTABLE(switch_mm)
142e209950fSRussell King
143e209950fSRussell King /* These two are private to arch/arm/kernel/suspend.c */
144e209950fSRussell King #define cpu_do_suspend PROC_VTABLE(do_suspend)
145e209950fSRussell King #define cpu_do_resume PROC_VTABLE(do_resume)
1464baa9922SRussell King #endif
1474baa9922SRussell King
148f6b0fa02SRussell King extern void cpu_resume(void);
149f6b0fa02SRussell King
1504baa9922SRussell King #ifdef CONFIG_MMU
1514baa9922SRussell King
1524baa9922SRussell King #define cpu_switch_mm(pgd,mm) cpu_do_switch_mm(virt_to_phys(pgd),mm)
1534baa9922SRussell King
154da028779SCatalin Marinas #ifdef CONFIG_ARM_LPAE
1551fc84ae8SCyril Chemparathy
1561fc84ae8SCyril Chemparathy #define cpu_get_ttbr(nr) \
1571fc84ae8SCyril Chemparathy ({ \
1581fc84ae8SCyril Chemparathy u64 ttbr; \
1591fc84ae8SCyril Chemparathy __asm__("mrrc p15, " #nr ", %Q0, %R0, c2" \
1601fc84ae8SCyril Chemparathy : "=r" (ttbr)); \
1611fc84ae8SCyril Chemparathy ttbr; \
1621fc84ae8SCyril Chemparathy })
1631fc84ae8SCyril Chemparathy
164da028779SCatalin Marinas #define cpu_get_pgd() \
165da028779SCatalin Marinas ({ \
1661fc84ae8SCyril Chemparathy u64 pg = cpu_get_ttbr(0); \
167da028779SCatalin Marinas pg &= ~(PTRS_PER_PGD*sizeof(pgd_t)-1); \
168da028779SCatalin Marinas (pgd_t *)phys_to_virt(pg); \
169da028779SCatalin Marinas })
170da028779SCatalin Marinas #else
1714baa9922SRussell King #define cpu_get_pgd() \
1724baa9922SRussell King ({ \
1734baa9922SRussell King unsigned long pg; \
1744baa9922SRussell King __asm__("mrc p15, 0, %0, c2, c0, 0" \
1754baa9922SRussell King : "=r" (pg) : : "cc"); \
1764baa9922SRussell King pg &= ~0x3fff; \
1774baa9922SRussell King (pgd_t *)phys_to_virt(pg); \
1784baa9922SRussell King })
179da028779SCatalin Marinas #endif
1804baa9922SRussell King
18102ed1c7bSWill Deacon #else /*!CONFIG_MMU */
18202ed1c7bSWill Deacon
18302ed1c7bSWill Deacon #define cpu_switch_mm(pgd,mm) { }
18402ed1c7bSWill Deacon
1854baa9922SRussell King #endif
1864baa9922SRussell King
1874baa9922SRussell King #endif /* __ASSEMBLY__ */
1884baa9922SRussell King #endif /* __KERNEL__ */
1894baa9922SRussell King #endif /* __ASM_PROCFNS_H */
190