xref: /kvm-unit-tests/lib/s390x/asm/time.h (revision 5bf99cb38621d44b0a7d2204ecd9326b3209ab73)
16c9f99dfSJanosch Frank /* SPDX-License-Identifier: GPL-2.0-only */
265b436f2SPierre Morel /*
365b436f2SPierre Morel  * Clock utilities for s390
465b436f2SPierre Morel  *
565b436f2SPierre Morel  * Authors:
665b436f2SPierre Morel  *  Thomas Huth <thuth@redhat.com>
765b436f2SPierre Morel  *
865b436f2SPierre Morel  * Copied from the s390/intercept test by:
965b436f2SPierre Morel  *  Pierre Morel <pmorel@linux.ibm.com>
1065b436f2SPierre Morel  */
11eb5a1bbaSCornelia Huck #ifndef _ASMS390X_TIME_H_
12eb5a1bbaSCornelia Huck #define _ASMS390X_TIME_H_
1365b436f2SPierre Morel 
1408a584f7SNico Boehr #define S390_CLOCK_SHIFT_US	(63 - 51)
1508a584f7SNico Boehr 
1608a584f7SNico Boehr #define STCK_SHIFT_US	S390_CLOCK_SHIFT_US
174cb1ee8fSPierre Morel #define STCK_MAX	((1UL << 52) - 1)
184cb1ee8fSPierre Morel 
1908a584f7SNico Boehr #define CPU_TIMER_SHIFT_US	S390_CLOCK_SHIFT_US
2008a584f7SNico Boehr 
sck(uint64_t * time)21*282f2efaSNico Boehr static inline int sck(uint64_t *time)
22*282f2efaSNico Boehr {
23*282f2efaSNico Boehr 	int cc;
24*282f2efaSNico Boehr 
25*282f2efaSNico Boehr 	asm volatile(
26*282f2efaSNico Boehr 		"	sck %[time]\n"
27*282f2efaSNico Boehr 		"	ipm %[cc]\n"
28*282f2efaSNico Boehr 		"	srl %[cc],28\n"
29*282f2efaSNico Boehr 		: [cc] "=d"(cc)
30*282f2efaSNico Boehr 		: [time] "Q"(*time)
31*282f2efaSNico Boehr 		: "cc"
32*282f2efaSNico Boehr 	);
33*282f2efaSNico Boehr 
34*282f2efaSNico Boehr 	return cc;
35*282f2efaSNico Boehr }
36*282f2efaSNico Boehr 
stck(uint64_t * time)37*282f2efaSNico Boehr static inline int stck(uint64_t *time)
38*282f2efaSNico Boehr {
39*282f2efaSNico Boehr 	int cc;
40*282f2efaSNico Boehr 
41*282f2efaSNico Boehr 	asm volatile(
42*282f2efaSNico Boehr 		"	stck %[time]\n"
43*282f2efaSNico Boehr 		"	ipm %[cc]\n"
44*282f2efaSNico Boehr 		"	srl %[cc],28\n"
45*282f2efaSNico Boehr 		: [cc] "=d" (cc), [time] "=Q" (*time)
46*282f2efaSNico Boehr 		:
47*282f2efaSNico Boehr 		: "cc"
48*282f2efaSNico Boehr 	);
49*282f2efaSNico Boehr 
50*282f2efaSNico Boehr 	return cc;
51*282f2efaSNico Boehr }
52*282f2efaSNico Boehr 
stckf(uint64_t * time)53*282f2efaSNico Boehr static inline int stckf(uint64_t *time)
54*282f2efaSNico Boehr {
55*282f2efaSNico Boehr 	int cc;
56*282f2efaSNico Boehr 
57*282f2efaSNico Boehr 	asm volatile(
58*282f2efaSNico Boehr 		"	stckf %[time]\n"
59*282f2efaSNico Boehr 		"	ipm %[cc]\n"
60*282f2efaSNico Boehr 		"	srl %[cc],28\n"
61*282f2efaSNico Boehr 		: [cc] "=d" (cc), [time] "=Q" (*time)
62*282f2efaSNico Boehr 		:
63*282f2efaSNico Boehr 		: "cc"
64*282f2efaSNico Boehr 	);
65*282f2efaSNico Boehr 
66*282f2efaSNico Boehr 	return cc;
67*282f2efaSNico Boehr }
68*282f2efaSNico Boehr 
get_clock_us(void)694cb1ee8fSPierre Morel static inline uint64_t get_clock_us(void)
7065b436f2SPierre Morel {
7165b436f2SPierre Morel 	uint64_t clk;
7265b436f2SPierre Morel 
73*282f2efaSNico Boehr 	stck(&clk);
7465b436f2SPierre Morel 
754cb1ee8fSPierre Morel 	return clk >> STCK_SHIFT_US;
764cb1ee8fSPierre Morel }
774cb1ee8fSPierre Morel 
get_clock_ms(void)784cb1ee8fSPierre Morel static inline uint64_t get_clock_ms(void)
794cb1ee8fSPierre Morel {
804cb1ee8fSPierre Morel 	return get_clock_us() / 1000;
814cb1ee8fSPierre Morel }
824cb1ee8fSPierre Morel 
udelay(unsigned long us)834cb1ee8fSPierre Morel static inline void udelay(unsigned long us)
844cb1ee8fSPierre Morel {
854cb1ee8fSPierre Morel 	unsigned long startclk = get_clock_us();
864cb1ee8fSPierre Morel 	unsigned long c;
874cb1ee8fSPierre Morel 
884cb1ee8fSPierre Morel 	do {
894cb1ee8fSPierre Morel 		c = get_clock_us();
904cb1ee8fSPierre Morel 		if (c < startclk)
914cb1ee8fSPierre Morel 			c += STCK_MAX;
924cb1ee8fSPierre Morel 	} while (c < startclk + us);
934cb1ee8fSPierre Morel }
944cb1ee8fSPierre Morel 
mdelay(unsigned long ms)954cb1ee8fSPierre Morel static inline void mdelay(unsigned long ms)
964cb1ee8fSPierre Morel {
974cb1ee8fSPierre Morel 	udelay(ms * 1000);
9865b436f2SPierre Morel }
9965b436f2SPierre Morel 
cpu_timer_set_ms(int64_t timeout_ms)10008a584f7SNico Boehr static inline void cpu_timer_set_ms(int64_t timeout_ms)
10108a584f7SNico Boehr {
10208a584f7SNico Boehr 	int64_t timer_value = (timeout_ms * 1000) << CPU_TIMER_SHIFT_US;
10308a584f7SNico Boehr 
10408a584f7SNico Boehr 	asm volatile (
10508a584f7SNico Boehr 		"spt %[timer_value]\n"
10608a584f7SNico Boehr 		:
10708a584f7SNico Boehr 		: [timer_value] "Q" (timer_value)
10808a584f7SNico Boehr 	);
10908a584f7SNico Boehr }
11008a584f7SNico Boehr 
11165b436f2SPierre Morel #endif
112