summaryrefslogtreecommitdiff
path: root/arch/s390
diff options
context:
space:
mode:
authorMartin Schwidefsky <schwidefsky@de.ibm.com>2019-02-14 15:40:56 +0100
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2019-03-23 14:35:20 +0100
commit6f87f879251d214ed8cd1ef8a6b7df5a612395c7 (patch)
tree5ecd0daf09b81b7dabc109ab81a2c7cbf1cac932 /arch/s390
parentfddab0355a57d193eb82139dc6ae2215cb64ee43 (diff)
s390/setup: fix early warning messages
commit 8727638426b0aea59d7f904ad8ddf483f9234f88 upstream. The setup_lowcore() function creates a new prefix page for the boot CPU. The PSW mask for the system_call, external interrupt, i/o interrupt and the program check handler have the DAT bit set in this new prefix page. At the time setup_lowcore is called the system still runs without virtual address translation, the paging_init() function creates the kernel page table and loads the CR13 with the kernel ASCE. Any code between setup_lowcore() and the end of paging_init() that has a BUG or WARN statement will create a program check that can not be handled correctly as there is no kernel page table yet. To allow early WARN statements initially setup the lowcore with DAT off and set the DAT bit only after paging_init() has completed. Cc: stable@vger.kernel.org Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'arch/s390')
-rw-r--r--arch/s390/kernel/setup.c32
1 files changed, 23 insertions, 9 deletions
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
index 3cb71fc94995..a9f5323f2f51 100644
--- a/arch/s390/kernel/setup.c
+++ b/arch/s390/kernel/setup.c
@@ -300,7 +300,7 @@ early_param("vmalloc", parse_vmalloc);
void *restart_stack __section(.data);
-static void __init setup_lowcore(void)
+static void __init setup_lowcore_dat_off(void)
{
struct lowcore *lc;
@@ -311,19 +311,16 @@ static void __init setup_lowcore(void)
lc = memblock_virt_alloc_low(sizeof(*lc), sizeof(*lc));
lc->restart_psw.mask = PSW_KERNEL_BITS;
lc->restart_psw.addr = (unsigned long) restart_int_handler;
- lc->external_new_psw.mask = PSW_KERNEL_BITS |
- PSW_MASK_DAT | PSW_MASK_MCHECK;
+ lc->external_new_psw.mask = PSW_KERNEL_BITS | PSW_MASK_MCHECK;
lc->external_new_psw.addr = (unsigned long) ext_int_handler;
lc->svc_new_psw.mask = PSW_KERNEL_BITS |
- PSW_MASK_DAT | PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK;
+ PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK;
lc->svc_new_psw.addr = (unsigned long) system_call;
- lc->program_new_psw.mask = PSW_KERNEL_BITS |
- PSW_MASK_DAT | PSW_MASK_MCHECK;
+ lc->program_new_psw.mask = PSW_KERNEL_BITS | PSW_MASK_MCHECK;
lc->program_new_psw.addr = (unsigned long) pgm_check_handler;
lc->mcck_new_psw.mask = PSW_KERNEL_BITS;
lc->mcck_new_psw.addr = (unsigned long) mcck_int_handler;
- lc->io_new_psw.mask = PSW_KERNEL_BITS |
- PSW_MASK_DAT | PSW_MASK_MCHECK;
+ lc->io_new_psw.mask = PSW_KERNEL_BITS | PSW_MASK_MCHECK;
lc->io_new_psw.addr = (unsigned long) io_int_handler;
lc->clock_comparator = clock_comparator_max;
lc->kernel_stack = ((unsigned long) &init_thread_union)
@@ -391,6 +388,17 @@ static void __init setup_lowcore(void)
lowcore_ptr[0] = lc;
}
+static void __init setup_lowcore_dat_on(void)
+{
+ struct lowcore *lc;
+
+ lc = lowcore_ptr[0];
+ lc->external_new_psw.mask |= PSW_MASK_DAT;
+ lc->svc_new_psw.mask |= PSW_MASK_DAT;
+ lc->program_new_psw.mask |= PSW_MASK_DAT;
+ lc->io_new_psw.mask |= PSW_MASK_DAT;
+}
+
static struct resource code_resource = {
.name = "Kernel code",
.flags = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM,
@@ -948,7 +956,7 @@ void __init setup_arch(char **cmdline_p)
#endif
setup_resources();
- setup_lowcore();
+ setup_lowcore_dat_off();
smp_fill_possible_mask();
cpu_detect_mhz_feature();
cpu_init();
@@ -961,6 +969,12 @@ void __init setup_arch(char **cmdline_p)
*/
paging_init();
+ /*
+ * After paging_init created the kernel page table, the new PSWs
+ * in lowcore can now run with DAT enabled.
+ */
+ setup_lowcore_dat_on();
+
/* Setup default console */
conmode_default();
set_preferred_console();