xref: /kvm-unit-tests/lib/arm64/asm/processor.h (revision 0917dc65eabbacb592456c0d1bb05e5828c23661)
17ee966e9SAndrew Jones #ifndef _ASMARM64_PROCESSOR_H_
27ee966e9SAndrew Jones #define _ASMARM64_PROCESSOR_H_
37ee966e9SAndrew Jones /*
47ee966e9SAndrew Jones  * Copyright (C) 2014, Red Hat Inc, Andrew Jones <drjones@redhat.com>
57ee966e9SAndrew Jones  *
67ee966e9SAndrew Jones  * This work is licensed under the terms of the GNU LGPL, version 2.
77ee966e9SAndrew Jones  */
8db328a24SAndrew Jones 
9db328a24SAndrew Jones /* System Control Register (SCTLR_EL1) bits */
10db328a24SAndrew Jones #define SCTLR_EL1_EE	(1 << 25)
11db328a24SAndrew Jones #define SCTLR_EL1_WXN	(1 << 19)
12db328a24SAndrew Jones #define SCTLR_EL1_I	(1 << 12)
13db328a24SAndrew Jones #define SCTLR_EL1_SA0	(1 << 4)
14db328a24SAndrew Jones #define SCTLR_EL1_SA	(1 << 3)
15db328a24SAndrew Jones #define SCTLR_EL1_C	(1 << 2)
16db328a24SAndrew Jones #define SCTLR_EL1_A	(1 << 1)
17db328a24SAndrew Jones #define SCTLR_EL1_M	(1 << 0)
18db328a24SAndrew Jones 
19410b3bf0SAlexandru Elisei #define CTR_DMINLINE_SHIFT	16
20410b3bf0SAlexandru Elisei #define CTR_DMINLINE_MASK	(0xf << 16)
21410b3bf0SAlexandru Elisei #define CTR_DMINLINE(x)	\
22410b3bf0SAlexandru Elisei 	(((x) & CTR_DMINLINE_MASK) >> CTR_DMINLINE_SHIFT)
23410b3bf0SAlexandru Elisei 
24db328a24SAndrew Jones #ifndef __ASSEMBLY__
257ee966e9SAndrew Jones #include <asm/ptrace.h>
26957b6055SAndrew Jones #include <asm/esr.h>
2792fca209SWei Huang #include <asm/sysreg.h>
28a5875fd4SAndrew Jones #include <asm/barrier.h>
297ee966e9SAndrew Jones 
307ee966e9SAndrew Jones enum vector {
317ee966e9SAndrew Jones 	EL1T_SYNC,
327ee966e9SAndrew Jones 	EL1T_IRQ,
337ee966e9SAndrew Jones 	EL1T_FIQ,
347ee966e9SAndrew Jones 	EL1T_ERROR,
357ee966e9SAndrew Jones 	EL1H_SYNC,
367ee966e9SAndrew Jones 	EL1H_IRQ,
377ee966e9SAndrew Jones 	EL1H_FIQ,
387ee966e9SAndrew Jones 	EL1H_ERROR,
397ee966e9SAndrew Jones 	EL0_SYNC_64,
407ee966e9SAndrew Jones 	EL0_IRQ_64,
417ee966e9SAndrew Jones 	EL0_FIQ_64,
427ee966e9SAndrew Jones 	EL0_ERROR_64,
437ee966e9SAndrew Jones 	EL0_SYNC_32,
447ee966e9SAndrew Jones 	EL0_IRQ_32,
457ee966e9SAndrew Jones 	EL0_FIQ_32,
467ee966e9SAndrew Jones 	EL0_ERROR_32,
477ee966e9SAndrew Jones 	VECTOR_MAX,
487ee966e9SAndrew Jones };
497ee966e9SAndrew Jones 
507ee966e9SAndrew Jones #define EC_MAX 64
517ee966e9SAndrew Jones 
527ee966e9SAndrew Jones typedef void (*vector_fn)(enum vector v, struct pt_regs *regs,
537ee966e9SAndrew Jones 			  unsigned int esr);
547ee966e9SAndrew Jones typedef void (*exception_fn)(struct pt_regs *regs, unsigned int esr);
559ae19a63SAndrew Jones typedef void (*irq_handler_fn)(struct pt_regs *regs);
567ee966e9SAndrew Jones extern void install_vector_handler(enum vector v, vector_fn fn);
577ee966e9SAndrew Jones extern void install_exception_handler(enum vector v, unsigned int ec,
587ee966e9SAndrew Jones 				      exception_fn fn);
599ae19a63SAndrew Jones extern void install_irq_handler(enum vector v, irq_handler_fn fn);
609ae19a63SAndrew Jones extern void default_vector_sync_handler(enum vector v, struct pt_regs *regs,
619ae19a63SAndrew Jones 					unsigned int esr);
629ae19a63SAndrew Jones extern void default_vector_irq_handler(enum vector v, struct pt_regs *regs,
63a4049322SAndrew Jones 				       unsigned int esr);
64ad14f089SAndrew Jones extern void vector_handlers_default_init(vector_fn *handlers);
657ee966e9SAndrew Jones 
667ee966e9SAndrew Jones extern void show_regs(struct pt_regs *regs);
67db328a24SAndrew Jones extern bool get_far(unsigned int esr, unsigned long *far);
687ee966e9SAndrew Jones 
697ee966e9SAndrew Jones static inline unsigned long current_level(void)
707ee966e9SAndrew Jones {
717ee966e9SAndrew Jones 	unsigned long el;
727ee966e9SAndrew Jones 	asm volatile("mrs %0, CurrentEL" : "=r" (el));
737ee966e9SAndrew Jones 	return el & 0xc;
747ee966e9SAndrew Jones }
757ee966e9SAndrew Jones 
76990e5425SAndrew Jones static inline void local_irq_enable(void)
77990e5425SAndrew Jones {
78990e5425SAndrew Jones 	asm volatile("msr daifclr, #2" : : : "memory");
79990e5425SAndrew Jones }
80990e5425SAndrew Jones 
81990e5425SAndrew Jones static inline void local_irq_disable(void)
82990e5425SAndrew Jones {
83990e5425SAndrew Jones 	asm volatile("msr daifset, #2" : : : "memory");
84990e5425SAndrew Jones }
85990e5425SAndrew Jones 
86da905c9dSAndrew Jones static inline uint64_t get_mpidr(void)
8792fca209SWei Huang {
8892fca209SWei Huang 	return read_sysreg(mpidr_el1);
89f6d10793SAndrew Jones }
90f6d10793SAndrew Jones 
91d9729025SAndrew Jones #define MPIDR_HWID_BITMASK 0xff00ffffff
92d9729025SAndrew Jones extern int mpidr_to_cpu(uint64_t mpidr);
93d9729025SAndrew Jones 
94d9729025SAndrew Jones #define MPIDR_LEVEL_SHIFT(level) \
95d9729025SAndrew Jones 	(((1 << level) >> 1) << 3)
96d9729025SAndrew Jones #define MPIDR_AFFINITY_LEVEL(mpidr, level) \
97d9729025SAndrew Jones 	((mpidr >> MPIDR_LEVEL_SHIFT(level)) & 0xff)
98f6d10793SAndrew Jones 
997ee966e9SAndrew Jones extern void start_usr(void (*func)(void *arg), void *arg, unsigned long sp_usr);
100f6d10793SAndrew Jones extern bool is_user(void);
101*0917dc65SNikos Nikoleris extern bool __mmu_enabled(void);
1027ee966e9SAndrew Jones 
103a5875fd4SAndrew Jones static inline u64 get_cntvct(void)
104a5875fd4SAndrew Jones {
105a5875fd4SAndrew Jones 	isb();
106a5875fd4SAndrew Jones 	return read_sysreg(cntvct_el0);
107a5875fd4SAndrew Jones }
108a5875fd4SAndrew Jones 
109a5875fd4SAndrew Jones static inline u32 get_cntfrq(void)
110a5875fd4SAndrew Jones {
111a5875fd4SAndrew Jones 	return read_sysreg(cntfrq_el0);
112a5875fd4SAndrew Jones }
113a5875fd4SAndrew Jones 
114410b3bf0SAlexandru Elisei static inline u64 get_ctr(void)
115410b3bf0SAlexandru Elisei {
116410b3bf0SAlexandru Elisei 	return read_sysreg(ctr_el0);
117410b3bf0SAlexandru Elisei }
118410b3bf0SAlexandru Elisei 
119956e3800SAndrew Jones extern unsigned long dcache_line_size;
120410b3bf0SAlexandru Elisei 
121c67363eeSNikos Nikoleris static inline unsigned long get_id_aa64mmfr0_el1(void)
122c67363eeSNikos Nikoleris {
123c67363eeSNikos Nikoleris 	return read_sysreg(id_aa64mmfr0_el1);
124c67363eeSNikos Nikoleris }
125c67363eeSNikos Nikoleris 
126c67363eeSNikos Nikoleris #define ID_AA64MMFR0_TGRAN4_SHIFT	28
127c67363eeSNikos Nikoleris #define ID_AA64MMFR0_TGRAN64_SHIFT	24
128c67363eeSNikos Nikoleris #define ID_AA64MMFR0_TGRAN16_SHIFT	20
129c67363eeSNikos Nikoleris 
130c67363eeSNikos Nikoleris #define ID_AA64MMFR0_TGRAN4_SUPPORTED	0x0
131c67363eeSNikos Nikoleris #define ID_AA64MMFR0_TGRAN64_SUPPORTED	0x0
132c67363eeSNikos Nikoleris #define ID_AA64MMFR0_TGRAN16_SUPPORTED	0x1
133c67363eeSNikos Nikoleris 
134c67363eeSNikos Nikoleris static inline bool system_supports_granule(size_t granule)
135c67363eeSNikos Nikoleris {
136c67363eeSNikos Nikoleris 	u32 shift;
137c67363eeSNikos Nikoleris 	u32 val;
138c67363eeSNikos Nikoleris 	u64 mmfr0;
139c67363eeSNikos Nikoleris 
140c67363eeSNikos Nikoleris 	if (granule == SZ_4K) {
141c67363eeSNikos Nikoleris 		shift = ID_AA64MMFR0_TGRAN4_SHIFT;
142c67363eeSNikos Nikoleris 		val = ID_AA64MMFR0_TGRAN4_SUPPORTED;
143c67363eeSNikos Nikoleris 	} else if (granule == SZ_16K) {
144c67363eeSNikos Nikoleris 		shift = ID_AA64MMFR0_TGRAN16_SHIFT;
145c67363eeSNikos Nikoleris 		val = ID_AA64MMFR0_TGRAN16_SUPPORTED;
146c67363eeSNikos Nikoleris 	} else {
147c67363eeSNikos Nikoleris 		assert(granule == SZ_64K);
148c67363eeSNikos Nikoleris 		shift = ID_AA64MMFR0_TGRAN64_SHIFT;
149c67363eeSNikos Nikoleris 		val = ID_AA64MMFR0_TGRAN64_SUPPORTED;
150c67363eeSNikos Nikoleris 	}
151c67363eeSNikos Nikoleris 
152c67363eeSNikos Nikoleris 	mmfr0 = get_id_aa64mmfr0_el1();
153c67363eeSNikos Nikoleris 
154c67363eeSNikos Nikoleris 	return ((mmfr0 >> shift) & 0xf) == val;
155c67363eeSNikos Nikoleris }
156c67363eeSNikos Nikoleris 
157db328a24SAndrew Jones #endif /* !__ASSEMBLY__ */
1587ee966e9SAndrew Jones #endif /* _ASMARM64_PROCESSOR_H_ */
159