aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390
diff options
context:
space:
mode:
authorMichael Holzheu <holzheu@linux.vnet.ibm.com>2012-05-24 08:35:16 -0400
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2012-05-30 03:04:49 -0400
commit73bf463efaba6a1efe69349c6d7275d03468adf4 (patch)
tree66a5c2eb6cc72bd8e627ba88931a23e1fdb25248 /arch/s390
parentf4815ac6c935b8e441fe12504d62e0e8ff7f7ce5 (diff)
s390/kernel: Introduce memcpy_absolute() function
This patch introduces the new function memcpy_absolute() that allows to copy memory using absolute addressing. This means that the prefix swap does not apply when this function is used. With this patch also all s390 kernel code that accesses absolute zero now uses the new memcpy_absolute() function. The old and less generic copy_to_absolute_zero() function is removed. Signed-off-by: Michael Holzheu <holzheu@linux.vnet.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'arch/s390')
-rw-r--r--arch/s390/include/asm/uaccess.h2
-rw-r--r--arch/s390/kernel/ipl.c15
-rw-r--r--arch/s390/kernel/os_info.c2
-rw-r--r--arch/s390/kernel/setup.c12
-rw-r--r--arch/s390/mm/maccess.c38
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)
377} 377}
378 378
379extern int memcpy_real(void *, void *, size_t); 379extern int memcpy_real(void *, void *, size_t);
380extern void copy_to_absolute_zero(void *dest, void *src, size_t count); 380extern void memcpy_absolute(void *, void *, size_t);
381extern int copy_to_user_real(void __user *dest, void *src, size_t count); 381extern int copy_to_user_real(void __user *dest, void *src, size_t count);
382extern int copy_from_user_real(void *dest, void __user *src, size_t count); 382extern int copy_from_user_real(void *dest, void __user *src, size_t count);
383 383
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 = {
1528 1528
1529static void dump_reipl_run(struct shutdown_trigger *trigger) 1529static void dump_reipl_run(struct shutdown_trigger *trigger)
1530{ 1530{
1531 u32 csum; 1531 struct {
1532 1532 void *addr;
1533 csum = csum_partial(reipl_block_actual, reipl_block_actual->hdr.len, 0); 1533 __u32 csum;
1534 copy_to_absolute_zero(&S390_lowcore.ipib_checksum, &csum, sizeof(csum)); 1534 } __packed ipib;
1535 copy_to_absolute_zero(&S390_lowcore.ipib, &reipl_block_actual, 1535
1536 sizeof(reipl_block_actual)); 1536 ipib.csum = csum_partial(reipl_block_actual,
1537 reipl_block_actual->hdr.len, 0);
1538 ipib.addr = reipl_block_actual;
1539 memcpy_absolute(&S390_lowcore.ipib, &ipib, sizeof(ipib));
1537 dump_run(trigger); 1540 dump_run(trigger);
1538} 1541}
1539 1542
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)
60 os_info.version_minor = OS_INFO_VERSION_MINOR; 60 os_info.version_minor = OS_INFO_VERSION_MINOR;
61 os_info.magic = OS_INFO_MAGIC; 61 os_info.magic = OS_INFO_MAGIC;
62 os_info.csum = os_info_csum(&os_info); 62 os_info.csum = os_info_csum(&os_info);
63 copy_to_absolute_zero(&S390_lowcore.os_info, &ptr, sizeof(ptr)); 63 memcpy_absolute(&S390_lowcore.os_info, &ptr, sizeof(ptr));
64} 64}
65 65
66#ifdef CONFIG_CRASH_DUMP 66#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)
428 lc->restart_fn = (unsigned long) do_restart; 428 lc->restart_fn = (unsigned long) do_restart;
429 lc->restart_data = 0; 429 lc->restart_data = 0;
430 lc->restart_source = -1UL; 430 lc->restart_source = -1UL;
431 memcpy(&S390_lowcore.restart_stack, &lc->restart_stack, 431
432 4*sizeof(unsigned long)); 432 /* Setup absolute zero lowcore */
433 copy_to_absolute_zero(&S390_lowcore.restart_psw, 433 memcpy_absolute(&S390_lowcore.restart_stack, &lc->restart_stack,
434 &lc->restart_psw, sizeof(psw_t)); 434 4 * sizeof(unsigned long));
435 memcpy_absolute(&S390_lowcore.restart_psw, &lc->restart_psw,
436 sizeof(lc->restart_psw));
435 437
436 set_prefix((u32)(unsigned long) lc); 438 set_prefix((u32)(unsigned long) lc);
437 lowcore_ptr[0] = lc; 439 lowcore_ptr[0] = lc;
@@ -598,7 +600,7 @@ static void __init setup_vmcoreinfo(void)
598#ifdef CONFIG_KEXEC 600#ifdef CONFIG_KEXEC
599 unsigned long ptr = paddr_vmcoreinfo_note(); 601 unsigned long ptr = paddr_vmcoreinfo_note();
600 602
601 copy_to_absolute_zero(&S390_lowcore.vmcore_info, &ptr, sizeof(ptr)); 603 memcpy_absolute(&S390_lowcore.vmcore_info, &ptr, sizeof(ptr));
602#endif 604#endif
603} 605}
604 606
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)
101} 101}
102 102
103/* 103/*
104 * Copy memory to absolute zero 104 * Copy memory in absolute mode (kernel to kernel)
105 */ 105 */
106void copy_to_absolute_zero(void *dest, void *src, size_t count) 106void memcpy_absolute(void *dest, void *src, size_t count)
107{ 107{
108 unsigned long cr0; 108 unsigned long cr0, flags, prefix;
109 109
110 BUG_ON((unsigned long) dest + count >= sizeof(struct _lowcore)); 110 flags = arch_local_irq_save();
111 preempt_disable();
112 __ctl_store(cr0, 0, 0); 111 __ctl_store(cr0, 0, 0);
113 __ctl_clear_bit(0, 28); /* disable lowcore protection */ 112 __ctl_clear_bit(0, 28); /* disable lowcore protection */
114 memcpy_real(dest + store_prefix(), src, count); 113 prefix = store_prefix();
114 if (prefix) {
115 local_mcck_disable();
116 set_prefix(0);
117 memcpy(dest, src, count);
118 set_prefix(prefix);
119 local_mcck_enable();
120 } else {
121 memcpy(dest, src, count);
122 }
115 __ctl_load(cr0, 0, 0); 123 __ctl_load(cr0, 0, 0);
116 preempt_enable(); 124 arch_local_irq_restore(flags);
117} 125}
118 126
119/* 127/*
@@ -188,20 +196,6 @@ static int is_swapped(unsigned long addr)
188} 196}
189 197
190/* 198/*
191 * Return swapped prefix or zero page address
192 */
193static unsigned long get_swapped(unsigned long addr)
194{
195 unsigned long prefix = store_prefix();
196
197 if (addr < sizeof(struct _lowcore))
198 return addr + prefix;
199 if (addr >= prefix && addr < prefix + sizeof(struct _lowcore))
200 return addr - prefix;
201 return addr;
202}
203
204/*
205 * Convert a physical pointer for /dev/mem access 199 * Convert a physical pointer for /dev/mem access
206 * 200 *
207 * For swapped prefix pages a new buffer is returned that contains a copy of 201 * 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)
218 size = PAGE_SIZE - (addr & ~PAGE_MASK); 212 size = PAGE_SIZE - (addr & ~PAGE_MASK);
219 bounce = (void *) __get_free_page(GFP_ATOMIC); 213 bounce = (void *) __get_free_page(GFP_ATOMIC);
220 if (bounce) 214 if (bounce)
221 memcpy_real(bounce, (void *) get_swapped(addr), size); 215 memcpy_absolute(bounce, (void *) addr, size);
222 } 216 }
223 preempt_enable(); 217 preempt_enable();
224 put_online_cpus(); 218 put_online_cpus();