xref: /openbmc/linux/arch/arm/include/asm/proc-fns.h (revision a9ff6961)
1d2912cb1SThomas 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