xref: /kvm-unit-tests/lib/s390x/asm/time.h (revision 08a584f79914bf4489a18275d24dc724cc6aecfe)
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 
14*08a584f7SNico Boehr #define S390_CLOCK_SHIFT_US	(63 - 51)
15*08a584f7SNico Boehr 
16*08a584f7SNico Boehr #define STCK_SHIFT_US	S390_CLOCK_SHIFT_US
174cb1ee8fSPierre Morel #define STCK_MAX	((1UL << 52) - 1)
184cb1ee8fSPierre Morel 
19*08a584f7SNico Boehr #define CPU_TIMER_SHIFT_US	S390_CLOCK_SHIFT_US
20*08a584f7SNico Boehr 
214cb1ee8fSPierre Morel static inline uint64_t get_clock_us(void)
2265b436f2SPierre Morel {
2365b436f2SPierre Morel 	uint64_t clk;
2465b436f2SPierre Morel 
2565b436f2SPierre Morel 	asm volatile(" stck %0 " : : "Q"(clk) : "memory");
2665b436f2SPierre Morel 
274cb1ee8fSPierre Morel 	return clk >> STCK_SHIFT_US;
284cb1ee8fSPierre Morel }
294cb1ee8fSPierre Morel 
304cb1ee8fSPierre Morel static inline uint64_t get_clock_ms(void)
314cb1ee8fSPierre Morel {
324cb1ee8fSPierre Morel 	return get_clock_us() / 1000;
334cb1ee8fSPierre Morel }
344cb1ee8fSPierre Morel 
354cb1ee8fSPierre Morel static inline void udelay(unsigned long us)
364cb1ee8fSPierre Morel {
374cb1ee8fSPierre Morel 	unsigned long startclk = get_clock_us();
384cb1ee8fSPierre Morel 	unsigned long c;
394cb1ee8fSPierre Morel 
404cb1ee8fSPierre Morel 	do {
414cb1ee8fSPierre Morel 		c = get_clock_us();
424cb1ee8fSPierre Morel 		if (c < startclk)
434cb1ee8fSPierre Morel 			c += STCK_MAX;
444cb1ee8fSPierre Morel 	} while (c < startclk + us);
454cb1ee8fSPierre Morel }
464cb1ee8fSPierre Morel 
474cb1ee8fSPierre Morel static inline void mdelay(unsigned long ms)
484cb1ee8fSPierre Morel {
494cb1ee8fSPierre Morel 	udelay(ms * 1000);
5065b436f2SPierre Morel }
5165b436f2SPierre Morel 
52*08a584f7SNico Boehr static inline void cpu_timer_set_ms(int64_t timeout_ms)
53*08a584f7SNico Boehr {
54*08a584f7SNico Boehr 	int64_t timer_value = (timeout_ms * 1000) << CPU_TIMER_SHIFT_US;
55*08a584f7SNico Boehr 
56*08a584f7SNico Boehr 	asm volatile (
57*08a584f7SNico Boehr 		"spt %[timer_value]\n"
58*08a584f7SNico Boehr 		:
59*08a584f7SNico Boehr 		: [timer_value] "Q" (timer_value)
60*08a584f7SNico Boehr 	);
61*08a584f7SNico Boehr }
62*08a584f7SNico Boehr 
6365b436f2SPierre Morel #endif
64