diff options
Diffstat (limited to 'arch/s390/mm/maccess.c')
-rw-r--r-- | arch/s390/mm/maccess.c | 38 |
1 files changed, 16 insertions, 22 deletions
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 | */ |
106 | void copy_to_absolute_zero(void *dest, void *src, size_t count) | 106 | void 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 | */ | ||
193 | static 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(); |