xref: /kvm-unit-tests/lib/arm64/asm/processor.h (revision 0cc3a351b925928827baa4b69cf0e46ff5837083)
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 
9*0cc3a351SSean Christopherson #ifndef __ASSEMBLER__
107ee966e9SAndrew Jones #include <asm/ptrace.h>
11957b6055SAndrew Jones #include <asm/esr.h>
1292fca209SWei Huang #include <asm/sysreg.h>
13a5875fd4SAndrew Jones #include <asm/barrier.h>
147ee966e9SAndrew Jones 
157ee966e9SAndrew Jones enum vector {
167ee966e9SAndrew Jones 	EL1T_SYNC,
177ee966e9SAndrew Jones 	EL1T_IRQ,
187ee966e9SAndrew Jones 	EL1T_FIQ,
197ee966e9SAndrew Jones 	EL1T_ERROR,
207ee966e9SAndrew Jones 	EL1H_SYNC,
217ee966e9SAndrew Jones 	EL1H_IRQ,
227ee966e9SAndrew Jones 	EL1H_FIQ,
237ee966e9SAndrew Jones 	EL1H_ERROR,
247ee966e9SAndrew Jones 	EL0_SYNC_64,
257ee966e9SAndrew Jones 	EL0_IRQ_64,
267ee966e9SAndrew Jones 	EL0_FIQ_64,
277ee966e9SAndrew Jones 	EL0_ERROR_64,
287ee966e9SAndrew Jones 	EL0_SYNC_32,
297ee966e9SAndrew Jones 	EL0_IRQ_32,
307ee966e9SAndrew Jones 	EL0_FIQ_32,
317ee966e9SAndrew Jones 	EL0_ERROR_32,
327ee966e9SAndrew Jones 	VECTOR_MAX,
337ee966e9SAndrew Jones };
347ee966e9SAndrew Jones 
357ee966e9SAndrew Jones #define EC_MAX 64
367ee966e9SAndrew Jones 
377ee966e9SAndrew Jones typedef void (*vector_fn)(enum vector v, struct pt_regs *regs,
387ee966e9SAndrew Jones 			  unsigned int esr);
397ee966e9SAndrew Jones typedef void (*exception_fn)(struct pt_regs *regs, unsigned int esr);
409ae19a63SAndrew Jones typedef void (*irq_handler_fn)(struct pt_regs *regs);
417ee966e9SAndrew Jones extern void install_vector_handler(enum vector v, vector_fn fn);
427ee966e9SAndrew Jones extern void install_exception_handler(enum vector v, unsigned int ec,
437ee966e9SAndrew Jones 				      exception_fn fn);
449ae19a63SAndrew Jones extern void install_irq_handler(enum vector v, irq_handler_fn fn);
459ae19a63SAndrew Jones extern void default_vector_sync_handler(enum vector v, struct pt_regs *regs,
469ae19a63SAndrew Jones 					unsigned int esr);
479ae19a63SAndrew Jones extern void default_vector_irq_handler(enum vector v, struct pt_regs *regs,
48a4049322SAndrew Jones 				       unsigned int esr);
49ad14f089SAndrew Jones extern void vector_handlers_default_init(vector_fn *handlers);
507ee966e9SAndrew Jones 
517ee966e9SAndrew Jones extern void show_regs(struct pt_regs *regs);
52db328a24SAndrew Jones extern bool get_far(unsigned int esr, unsigned long *far);
537ee966e9SAndrew Jones 
current_level(void)547ee966e9SAndrew Jones static inline unsigned long current_level(void)
557ee966e9SAndrew Jones {
567ee966e9SAndrew Jones 	unsigned long el;
577ee966e9SAndrew Jones 	asm volatile("mrs %0, CurrentEL" : "=r" (el));
587ee966e9SAndrew Jones 	return el & 0xc;
597ee966e9SAndrew Jones }
607ee966e9SAndrew Jones 
local_irq_enable(void)61990e5425SAndrew Jones static inline void local_irq_enable(void)
62990e5425SAndrew Jones {
63990e5425SAndrew Jones 	asm volatile("msr daifclr, #2" : : : "memory");
64990e5425SAndrew Jones }
65990e5425SAndrew Jones 
local_irq_disable(void)66990e5425SAndrew Jones static inline void local_irq_disable(void)
67990e5425SAndrew Jones {
68990e5425SAndrew Jones 	asm volatile("msr daifset, #2" : : : "memory");
69990e5425SAndrew Jones }
70990e5425SAndrew Jones 
get_mpidr(void)71da905c9dSAndrew Jones static inline uint64_t get_mpidr(void)
7292fca209SWei Huang {
7392fca209SWei Huang 	return read_sysreg(mpidr_el1);
74f6d10793SAndrew Jones }
75f6d10793SAndrew Jones 
76d9729025SAndrew Jones #define MPIDR_HWID_BITMASK 0xff00ffffff
77d9729025SAndrew Jones extern int mpidr_to_cpu(uint64_t mpidr);
78d9729025SAndrew Jones 
79d9729025SAndrew Jones #define MPIDR_LEVEL_SHIFT(level) \
80d9729025SAndrew Jones 	(((1 << level) >> 1) << 3)
81d9729025SAndrew Jones #define MPIDR_AFFINITY_LEVEL(mpidr, level) \
82d9729025SAndrew Jones 	((mpidr >> MPIDR_LEVEL_SHIFT(level)) & 0xff)
83f6d10793SAndrew Jones 
847ee966e9SAndrew Jones extern void start_usr(void (*func)(void *arg), void *arg, unsigned long sp_usr);
85f6d10793SAndrew Jones extern bool is_user(void);
860917dc65SNikos Nikoleris extern bool __mmu_enabled(void);
877ee966e9SAndrew Jones 
get_cntvct(void)88a5875fd4SAndrew Jones static inline u64 get_cntvct(void)
89a5875fd4SAndrew Jones {
90a5875fd4SAndrew Jones 	isb();
91a5875fd4SAndrew Jones 	return read_sysreg(cntvct_el0);
92a5875fd4SAndrew Jones }
93a5875fd4SAndrew Jones 
get_cntfrq(void)94a5875fd4SAndrew Jones static inline u32 get_cntfrq(void)
95a5875fd4SAndrew Jones {
96a5875fd4SAndrew Jones 	return read_sysreg(cntfrq_el0);
97a5875fd4SAndrew Jones }
98a5875fd4SAndrew Jones 
get_ctr(void)99410b3bf0SAlexandru Elisei static inline u64 get_ctr(void)
100410b3bf0SAlexandru Elisei {
101410b3bf0SAlexandru Elisei 	return read_sysreg(ctr_el0);
102410b3bf0SAlexandru Elisei }
103410b3bf0SAlexandru Elisei 
get_id_aa64mmfr0_el1(void)104c67363eeSNikos Nikoleris static inline unsigned long get_id_aa64mmfr0_el1(void)
105c67363eeSNikos Nikoleris {
106c67363eeSNikos Nikoleris 	return read_sysreg(id_aa64mmfr0_el1);
107c67363eeSNikos Nikoleris }
108c67363eeSNikos Nikoleris 
109c67363eeSNikos Nikoleris #define ID_AA64MMFR0_TGRAN4_SHIFT	28
110c67363eeSNikos Nikoleris #define ID_AA64MMFR0_TGRAN64_SHIFT	24
111c67363eeSNikos Nikoleris #define ID_AA64MMFR0_TGRAN16_SHIFT	20
112c67363eeSNikos Nikoleris 
113dc0a3a76SAndrew Jones #define ID_AA64MMFR0_TGRAN4_SUPPORTED(r)			\
114dc0a3a76SAndrew Jones ({								\
115dc0a3a76SAndrew Jones 	u64 __v = ((r) >> ID_AA64MMFR0_TGRAN4_SHIFT) & 0xf;	\
116dc0a3a76SAndrew Jones 	(__v) == 0 || (__v) == 1;				\
117dc0a3a76SAndrew Jones })
118dc0a3a76SAndrew Jones 
119dc0a3a76SAndrew Jones #define ID_AA64MMFR0_TGRAN64_SUPPORTED(r)			\
120dc0a3a76SAndrew Jones ({								\
121dc0a3a76SAndrew Jones 	u64 __v = ((r) >> ID_AA64MMFR0_TGRAN64_SHIFT) & 0xf;	\
122dc0a3a76SAndrew Jones 	(__v) == 0;						\
123dc0a3a76SAndrew Jones })
124dc0a3a76SAndrew Jones 
125dc0a3a76SAndrew Jones #define ID_AA64MMFR0_TGRAN16_SUPPORTED(r)			\
126dc0a3a76SAndrew Jones ({								\
127dc0a3a76SAndrew Jones 	u64 __v = ((r) >> ID_AA64MMFR0_TGRAN16_SHIFT) & 0xf;	\
128dc0a3a76SAndrew Jones 	(__v) == 1 || (__v) == 2;				\
129dc0a3a76SAndrew Jones })
130c67363eeSNikos Nikoleris 
system_supports_granule(size_t granule)131c67363eeSNikos Nikoleris static inline bool system_supports_granule(size_t granule)
132c67363eeSNikos Nikoleris {
133dc0a3a76SAndrew Jones 	u64 mmfr0 = get_id_aa64mmfr0_el1();
134c67363eeSNikos Nikoleris 
135dc0a3a76SAndrew Jones 	if (granule == SZ_4K)
136dc0a3a76SAndrew Jones 		return ID_AA64MMFR0_TGRAN4_SUPPORTED(mmfr0);
137dc0a3a76SAndrew Jones 
138dc0a3a76SAndrew Jones 	if (granule == SZ_16K)
139dc0a3a76SAndrew Jones 		return ID_AA64MMFR0_TGRAN16_SUPPORTED(mmfr0);
140dc0a3a76SAndrew Jones 
141c67363eeSNikos Nikoleris 	assert(granule == SZ_64K);
142dc0a3a76SAndrew Jones 	return ID_AA64MMFR0_TGRAN64_SUPPORTED(mmfr0);
143c67363eeSNikos Nikoleris }
144c67363eeSNikos Nikoleris 
get_id_aa64pfr0_el1(void)145d47d370cSSubhasish Ghosh static inline unsigned long get_id_aa64pfr0_el1(void)
146d47d370cSSubhasish Ghosh {
147d47d370cSSubhasish Ghosh 	return read_sysreg(id_aa64pfr0_el1);
148d47d370cSSubhasish Ghosh }
149d47d370cSSubhasish Ghosh 
150d47d370cSSubhasish Ghosh #define ID_AA64PFR0_EL1_SVE_SHIFT	32
151d47d370cSSubhasish Ghosh 
system_supports_sve(void)152d47d370cSSubhasish Ghosh static inline bool system_supports_sve(void)
153d47d370cSSubhasish Ghosh {
154d47d370cSSubhasish Ghosh 	return ((get_id_aa64pfr0_el1() >> ID_AA64PFR0_EL1_SVE_SHIFT) & 0xf) != 0;
155d47d370cSSubhasish Ghosh }
156d47d370cSSubhasish Ghosh 
sve_vl(void)1570ed2cdf3SSuzuki K Poulose static inline unsigned long sve_vl(void)
158d47d370cSSubhasish Ghosh {
1590ed2cdf3SSuzuki K Poulose 	unsigned long vl;
160d47d370cSSubhasish Ghosh 
161d47d370cSSubhasish Ghosh 	asm volatile(".arch_extension sve\n"
1620ed2cdf3SSuzuki K Poulose 		     "rdvl %x0, #8"
163d47d370cSSubhasish Ghosh 		     : "=r" (vl));
164d47d370cSSubhasish Ghosh 
165d47d370cSSubhasish Ghosh 	return vl;
166d47d370cSSubhasish Ghosh }
167d47d370cSSubhasish Ghosh 
168d47d370cSSubhasish Ghosh 
system_supports_rndr(void)169d47d370cSSubhasish Ghosh static inline bool system_supports_rndr(void)
170d47d370cSSubhasish Ghosh {
171d47d370cSSubhasish Ghosh 	u64 id_aa64isar0_el1 = read_sysreg(ID_AA64ISAR0_EL1);
172d47d370cSSubhasish Ghosh 
173d47d370cSSubhasish Ghosh 	return ((id_aa64isar0_el1 >> ID_AA64ISAR0_EL1_RNDR_SHIFT) & 0xf) != 0;
174d47d370cSSubhasish Ghosh }
175d47d370cSSubhasish Ghosh 
176*0cc3a351SSean Christopherson #endif /* !__ASSEMBLER__ */
1777ee966e9SAndrew Jones #endif /* _ASMARM64_PROCESSOR_H_ */
178