|
1 | 1 | // SPDX-License-Identifier: GPL-2.0 |
2 | 2 | #include <linux/string.h> |
3 | 3 | #include <linux/elf.h> |
| 4 | +#include <asm/page-states.h> |
4 | 5 | #include <asm/boot_data.h> |
5 | 6 | #include <asm/sections.h> |
6 | 7 | #include <asm/maccess.h> |
@@ -57,6 +58,48 @@ static void detect_facilities(void) |
57 | 58 | machine.has_nx = 1; |
58 | 59 | } |
59 | 60 |
|
| 61 | +static int cmma_test_essa(void) |
| 62 | +{ |
| 63 | + unsigned long reg1, reg2, tmp = 0; |
| 64 | + int rc = 1; |
| 65 | + psw_t old; |
| 66 | + |
| 67 | + /* Test ESSA_GET_STATE */ |
| 68 | + asm volatile( |
| 69 | + " mvc 0(16,%[psw_old]),0(%[psw_pgm])\n" |
| 70 | + " epsw %[reg1],%[reg2]\n" |
| 71 | + " st %[reg1],0(%[psw_pgm])\n" |
| 72 | + " st %[reg2],4(%[psw_pgm])\n" |
| 73 | + " larl %[reg1],1f\n" |
| 74 | + " stg %[reg1],8(%[psw_pgm])\n" |
| 75 | + " .insn rrf,0xb9ab0000,%[tmp],%[tmp],%[cmd],0\n" |
| 76 | + " la %[rc],0\n" |
| 77 | + "1: mvc 0(16,%[psw_pgm]),0(%[psw_old])\n" |
| 78 | + : [reg1] "=&d" (reg1), |
| 79 | + [reg2] "=&a" (reg2), |
| 80 | + [rc] "+&d" (rc), |
| 81 | + [tmp] "=&d" (tmp), |
| 82 | + "+Q" (S390_lowcore.program_new_psw), |
| 83 | + "=Q" (old) |
| 84 | + : [psw_old] "a" (&old), |
| 85 | + [psw_pgm] "a" (&S390_lowcore.program_new_psw), |
| 86 | + [cmd] "i" (ESSA_GET_STATE) |
| 87 | + : "cc", "memory"); |
| 88 | + return rc; |
| 89 | +} |
| 90 | + |
| 91 | +static void cmma_init(void) |
| 92 | +{ |
| 93 | + if (!cmma_flag) |
| 94 | + return; |
| 95 | + if (cmma_test_essa()) { |
| 96 | + cmma_flag = 0; |
| 97 | + return; |
| 98 | + } |
| 99 | + if (test_facility(147)) |
| 100 | + cmma_flag = 2; |
| 101 | +} |
| 102 | + |
60 | 103 | static void setup_lpp(void) |
61 | 104 | { |
62 | 105 | S390_lowcore.current_pid = 0; |
@@ -306,6 +349,7 @@ void startup_kernel(void) |
306 | 349 | setup_boot_command_line(); |
307 | 350 | parse_boot_command_line(); |
308 | 351 | detect_facilities(); |
| 352 | + cmma_init(); |
309 | 353 | sanitize_prot_virt_host(); |
310 | 354 | max_physmem_end = detect_max_physmem_end(); |
311 | 355 | setup_ident_map_size(max_physmem_end); |
|
0 commit comments