diff --git a/arch/s390/include/asm/timex.h b/arch/s390/include/asm/timex.h
index 0f34db4238da4..0bb08f341c09b 100644
--- a/arch/s390/include/asm/timex.h
+++ b/arch/s390/include/asm/timex.h
@@ -56,11 +56,13 @@ void __init ptff_init(void);
 
 extern unsigned char ptff_function_mask[16];
 extern unsigned long lpar_offset;
+extern unsigned long initial_leap_seconds;
 
 /* Function codes for the ptff instruction. */
 #define PTFF_QAF	0x00	/* query available functions */
 #define PTFF_QTO	0x01	/* query tod offset */
 #define PTFF_QSI	0x02	/* query steering information */
+#define PTFF_QUI	0x04	/* query UTC information */
 #define PTFF_ATO	0x40	/* adjust tod offset */
 #define PTFF_STO	0x41	/* set tod offset */
 #define PTFF_SFS	0x42	/* set fine steering rate */
@@ -82,6 +84,22 @@ static inline int ptff_query(unsigned int nr)
 	return (*ptr & (0x80 >> (nr & 7))) != 0;
 }
 
+/* Query UTC information result */
+struct ptff_qui {
+	unsigned int tm : 2;
+	unsigned int ts : 2;
+	unsigned int : 28;
+	unsigned int pad_0x04;
+	unsigned long leap_event;
+	short old_leap;
+	short new_leap;
+	unsigned int pad_0x14;
+	unsigned long prt[5];
+	unsigned long cst[3];
+	unsigned int skew;
+	unsigned int pad_0x5c[41];
+} __packed;
+
 static inline int ptff(void *ptff_block, size_t len, unsigned int func)
 {
 	typedef struct { char _[len]; } addrtype;
diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c
index d716236399971..1a27d4d08b43c 100644
--- a/arch/s390/kernel/time.c
+++ b/arch/s390/kernel/time.c
@@ -64,6 +64,7 @@ EXPORT_SYMBOL(s390_epoch_delta_notifier);
 
 unsigned char ptff_function_mask[16];
 unsigned long lpar_offset;
+unsigned long initial_leap_seconds;
 
 /*
  * Get time offsets with PTFF
@@ -71,6 +72,7 @@ unsigned long lpar_offset;
 void __init ptff_init(void)
 {
 	struct ptff_qto qto;
+	struct ptff_qui qui;
 
 	if (!test_facility(28))
 		return;
@@ -79,6 +81,11 @@ void __init ptff_init(void)
 	/* get LPAR offset */
 	if (ptff_query(PTFF_QTO) && ptff(&qto, sizeof(qto), PTFF_QTO) == 0)
 		lpar_offset = qto.tod_epoch_difference;
+
+	/* get initial leap seconds */
+	if (ptff_query(PTFF_QUI) && ptff(&qui, sizeof(qui), PTFF_QUI) == 0)
+		initial_leap_seconds = (unsigned long)
+			((long) qui.old_leap * 4096000000L);
 }
 
 /*
@@ -200,12 +207,18 @@ static void stp_reset(void);
 
 void read_persistent_clock64(struct timespec64 *ts)
 {
-	tod_to_timeval(get_tod_clock() - TOD_UNIX_EPOCH, ts);
+	__u64 clock;
+
+	clock = get_tod_clock() - initial_leap_seconds;
+	tod_to_timeval(clock - TOD_UNIX_EPOCH, ts);
 }
 
 void read_boot_clock64(struct timespec64 *ts)
 {
-	tod_to_timeval(sched_clock_base_cc - TOD_UNIX_EPOCH, ts);
+	__u64 clock;
+
+	clock = sched_clock_base_cc - initial_leap_seconds;
+	tod_to_timeval(clock - TOD_UNIX_EPOCH, ts);
 }
 
 static cycle_t read_tod_clock(struct clocksource *cs)