diff options
Diffstat (limited to 'arch/s390')
-rw-r--r-- | arch/s390/include/asm/uaccess.h | 2 | ||||
-rw-r--r-- | arch/s390/kernel/ipl.c | 15 | ||||
-rw-r--r-- | arch/s390/kernel/os_info.c | 2 | ||||
-rw-r--r-- | arch/s390/kernel/setup.c | 12 | ||||
-rw-r--r-- | arch/s390/mm/maccess.c | 38 |
5 files changed, 34 insertions, 35 deletions
diff --git a/arch/s390/include/asm/uaccess.h b/arch/s390/include/asm/uaccess.h index 8f2cada4f7c9..8e83da66df0d 100644 --- a/arch/s390/include/asm/uaccess.h +++ b/arch/s390/include/asm/uaccess.h @@ -377,7 +377,7 @@ clear_user(void __user *to, unsigned long n) } extern int memcpy_real(void *, void *, size_t); -extern void copy_to_absolute_zero(void *dest, void *src, size_t count); +extern void memcpy_absolute(void *, void *, size_t); extern int copy_to_user_real(void __user *dest, void *src, size_t count); extern int copy_from_user_real(void *dest, void __user *src, size_t count); diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c index dcfdcb3ea163..2f6cfd460cb6 100644 --- a/arch/s390/kernel/ipl.c +++ b/arch/s390/kernel/ipl.c @@ -1528,12 +1528,15 @@ static struct shutdown_action __refdata dump_action = { static void dump_reipl_run(struct shutdown_trigger *trigger) { - u32 csum; - - csum = csum_partial(reipl_block_actual, reipl_block_actual->hdr.len, 0); - copy_to_absolute_zero(&S390_lowcore.ipib_checksum, &csum, sizeof(csum)); - copy_to_absolute_zero(&S390_lowcore.ipib, &reipl_block_actual, - sizeof(reipl_block_actual)); + struct { + void *addr; + __u32 csum; + } __packed ipib; + + ipib.csum = csum_partial(reipl_block_actual, + reipl_block_actual->hdr.len, 0); + ipib.addr = reipl_block_actual; + memcpy_absolute(&S390_lowcore.ipib, &ipib, sizeof(ipib)); dump_run(trigger); } diff --git a/arch/s390/kernel/os_info.c b/arch/s390/kernel/os_info.c index f2fe18f3f01f..95fa5ac6c4ce 100644 --- a/arch/s390/kernel/os_info.c +++ b/arch/s390/kernel/os_info.c @@ -60,7 +60,7 @@ void __init os_info_init(void) os_info.version_minor = OS_INFO_VERSION_MINOR; os_info.magic = OS_INFO_MAGIC; os_info.csum = os_info_csum(&os_info); - copy_to_absolute_zero(&S390_lowcore.os_info, &ptr, sizeof(ptr)); + memcpy_absolute(&S390_lowcore.os_info, &ptr, sizeof(ptr)); } #ifdef CONFIG_CRASH_DUMP diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index 06264ae8ccd9..489d1d8d96b0 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c @@ -428,10 +428,12 @@ static void __init setup_lowcore(void) lc->restart_fn = (unsigned long) do_restart; lc->restart_data = 0; lc->restart_source = -1UL; - memcpy(&S390_lowcore.restart_stack, &lc->restart_stack, - 4*sizeof(unsigned long)); - copy_to_absolute_zero(&S390_lowcore.restart_psw, - &lc->restart_psw, sizeof(psw_t)); + + /* Setup absolute zero lowcore */ + memcpy_absolute(&S390_lowcore.restart_stack, &lc->restart_stack, + 4 * sizeof(unsigned long)); + memcpy_absolute(&S390_lowcore.restart_psw, &lc->restart_psw, + sizeof(lc->restart_psw)); set_prefix((u32)(unsigned long) lc); lowcore_ptr[0] = lc; @@ -598,7 +600,7 @@ static void __init setup_vmcoreinfo(void) #ifdef CONFIG_KEXEC unsigned long ptr = paddr_vmcoreinfo_note(); - copy_to_absolute_zero(&S390_lowcore.vmcore_info, &ptr, sizeof(ptr)); + memcpy_absolute(&S390_lowcore.vmcore_info, &ptr, sizeof(ptr)); #endif } diff --git a/arch/s390/mm/maccess.c b/arch/s390/mm/maccess.c index 795a0a9bb2eb..921fa541dc04 100644 --- a/arch/s390/mm/maccess.c +++ b/arch/s390/mm/maccess.c @@ -101,19 +101,27 @@ int memcpy_real(void *dest, void *src, size_t count) } /* - * Copy memory to absolute zero + * Copy memory in absolute mode (kernel to kernel) */ -void copy_to_absolute_zero(void *dest, void *src, size_t count) +void memcpy_absolute(void *dest, void *src, size_t count) { - unsigned long cr0; + unsigned long cr0, flags, prefix; - BUG_ON((unsigned long) dest + count >= sizeof(struct _lowcore)); - preempt_disable(); + flags = arch_local_irq_save(); __ctl_store(cr0, 0, 0); __ctl_clear_bit(0, 28); /* disable lowcore protection */ - memcpy_real(dest + store_prefix(), src, count); + prefix = store_prefix(); + if (prefix) { + local_mcck_disable(); + set_prefix(0); + memcpy(dest, src, count); + set_prefix(prefix); + local_mcck_enable(); + } else { + memcpy(dest, src, count); + } __ctl_load(cr0, 0, 0); - preempt_enable(); + arch_local_irq_restore(flags); } /* @@ -188,20 +196,6 @@ static int is_swapped(unsigned long addr) } /* - * Return swapped prefix or zero page address - */ -static unsigned long get_swapped(unsigned long addr) -{ - unsigned long prefix = store_prefix(); - - if (addr < sizeof(struct _lowcore)) - return addr + prefix; - if (addr >= prefix && addr < prefix + sizeof(struct _lowcore)) - return addr - prefix; - return addr; -} - -/* * Convert a physical pointer for /dev/mem access * * For swapped prefix pages a new buffer is returned that contains a copy of @@ -218,7 +212,7 @@ void *xlate_dev_mem_ptr(unsigned long addr) size = PAGE_SIZE - (addr & ~PAGE_MASK); bounce = (void *) __get_free_page(GFP_ATOMIC); if (bounce) - memcpy_real(bounce, (void *) get_swapped(addr), size); + memcpy_absolute(bounce, (void *) addr, size); } preempt_enable(); put_online_cpus(); |