diff --git a/arch/s390/boot/boot.h b/arch/s390/boot/boot.h
index f6e82cf7851e27d6781eea916418f42b78ffc792..286441cf3bf0231883d85a9f23d4e54a3d5bb490 100644
--- a/arch/s390/boot/boot.h
+++ b/arch/s390/boot/boot.h
@@ -8,6 +8,12 @@
 
 #ifndef __ASSEMBLY__
 
+struct machine_info {
+	unsigned char has_edat1 : 1;
+	unsigned char has_edat2 : 1;
+	unsigned char has_nx : 1;
+};
+
 struct vmlinux_info {
 	unsigned long default_lma;
 	void (*entry)(void);
@@ -38,6 +44,8 @@ unsigned long get_random_base(unsigned long safe_addr);
 void __printf(1, 2) decompressor_printk(const char *fmt, ...);
 void error(char *m);
 
+extern struct machine_info machine;
+
 /* Symbols defined by linker scripts */
 extern const char kernel_version[];
 extern unsigned long memory_limit;
diff --git a/arch/s390/boot/startup.c b/arch/s390/boot/startup.c
index 47ca3264c02308d687128844b433cdd9c6436d8d..da6ee587fe9ac264d310f6b4d1ad1f8223fc36d9 100644
--- a/arch/s390/boot/startup.c
+++ b/arch/s390/boot/startup.c
@@ -33,6 +33,8 @@ u64 __bootdata_preserved(stfle_fac_list[16]);
 u64 __bootdata_preserved(alt_stfle_fac_list[16]);
 struct oldmem_data __bootdata_preserved(oldmem_data);
 
+struct machine_info machine;
+
 void error(char *x)
 {
 	sclp_early_printk("\n\n");
@@ -42,6 +44,20 @@ void error(char *x)
 	disabled_wait();
 }
 
+static void detect_facilities(void)
+{
+	if (test_facility(8)) {
+		machine.has_edat1 = 1;
+		__ctl_set_bit(0, 23);
+	}
+	if (test_facility(78))
+		machine.has_edat2 = 1;
+	if (!noexec_disabled && test_facility(130)) {
+		machine.has_nx = 1;
+		__ctl_set_bit(0, 20);
+	}
+}
+
 static void setup_lpp(void)
 {
 	S390_lowcore.current_pid = 0;
@@ -254,6 +270,8 @@ void startup_kernel(void)
 	unsigned long safe_addr;
 	void *img;
 
+	detect_facilities();
+
 	initrd_data.start = parmarea.initrd_start;
 	initrd_data.size = parmarea.initrd_size;
 	oldmem_data.start = parmarea.oldmem_base;