Skip to content

Commit

Permalink
[S390] zcore: CPU registers are not saved under LPAR
Browse files Browse the repository at this point in the history
To save the registers for all CPUs a sigp "store status" is done that
stores the registers to address absolute zero. To access storage at
absolute zero, normally the address of the prefix register of the
accessing CPU has to be used. This does not work when large pages are
active (currently only under LPAR). In order to fix that problem,
instead of memcpy memcpy_real is used, which switches to real mode
where prefixing works.

Signed-off-by: Michael Holzheu <holzheu@linux.vnet.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
  • Loading branch information
Michael Holzheu authored and Martin Schwidefsky committed Mar 24, 2010
1 parent ae6be51 commit 92fe313
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 32 deletions.
1 change: 1 addition & 0 deletions arch/s390/include/asm/system.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ extern void pfault_fini(void);
#endif /* CONFIG_PFAULT */

extern void cmma_init(void);
extern int memcpy_real(void *, void *, size_t);

#define finish_arch_switch(prev) do { \
set_fs(current->thread.mm_segment); \
Expand Down
6 changes: 3 additions & 3 deletions arch/s390/kernel/smp.c
Original file line number Diff line number Diff line change
Expand Up @@ -292,9 +292,9 @@ static void __init smp_get_save_area(unsigned int cpu, unsigned int phy_cpu)
zfcpdump_save_areas[cpu] = kmalloc(sizeof(struct save_area), GFP_KERNEL);
while (raw_sigp(phy_cpu, sigp_stop_and_store_status) == sigp_busy)
cpu_relax();
memcpy(zfcpdump_save_areas[cpu],
(void *)(unsigned long) store_prefix() + SAVE_AREA_BASE,
sizeof(struct save_area));
memcpy_real(zfcpdump_save_areas[cpu],
(void *)(unsigned long) store_prefix() + SAVE_AREA_BASE,
sizeof(struct save_area));
}

struct save_area *zfcpdump_save_areas[NR_CPUS + 1];
Expand Down
26 changes: 26 additions & 0 deletions arch/s390/mm/maccess.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,3 +59,29 @@ long probe_kernel_write(void *dst, void *src, size_t size)
}
return copied < 0 ? -EFAULT : 0;
}

int memcpy_real(void *dest, void *src, size_t count)
{
register unsigned long _dest asm("2") = (unsigned long) dest;
register unsigned long _len1 asm("3") = (unsigned long) count;
register unsigned long _src asm("4") = (unsigned long) src;
register unsigned long _len2 asm("5") = (unsigned long) count;
unsigned long flags;
int rc = -EFAULT;

if (!count)
return 0;
flags = __raw_local_irq_stnsm(0xf8UL);
asm volatile (
"0: mvcle %1,%2,0x0\n"
"1: jo 0b\n"
" lhi %0,0x0\n"
"2:\n"
EX_TABLE(1b,2b)
: "+d" (rc), "+d" (_dest), "+d" (_src), "+d" (_len1),
"+d" (_len2), "=m" (*((long *) dest))
: "m" (*((long *) src))
: "cc", "memory");
__raw_local_irq_ssm(flags);
return rc;
}
31 changes: 2 additions & 29 deletions drivers/s390/char/zcore.c
Original file line number Diff line number Diff line change
Expand Up @@ -141,41 +141,14 @@ static int memcpy_hsa_kernel(void *dest, unsigned long src, size_t count)
return memcpy_hsa(dest, src, count, TO_KERNEL);
}

static int memcpy_real(void *dest, unsigned long src, size_t count)
{
unsigned long flags;
int rc = -EFAULT;
register unsigned long _dest asm("2") = (unsigned long) dest;
register unsigned long _len1 asm("3") = (unsigned long) count;
register unsigned long _src asm("4") = src;
register unsigned long _len2 asm("5") = (unsigned long) count;

if (count == 0)
return 0;
flags = __raw_local_irq_stnsm(0xf8UL); /* switch to real mode */
asm volatile (
"0: mvcle %1,%2,0x0\n"
"1: jo 0b\n"
" lhi %0,0x0\n"
"2:\n"
EX_TABLE(1b,2b)
: "+d" (rc), "+d" (_dest), "+d" (_src), "+d" (_len1),
"+d" (_len2), "=m" (*((long*)dest))
: "m" (*((long*)src))
: "cc", "memory");
__raw_local_irq_ssm(flags);

return rc;
}

static int memcpy_real_user(void __user *dest, unsigned long src, size_t count)
{
static char buf[4096];
int offs = 0, size;

while (offs < count) {
size = min(sizeof(buf), count - offs);
if (memcpy_real(buf, src + offs, size))
if (memcpy_real(buf, (void *) src + offs, size))
return -EFAULT;
if (copy_to_user(dest + offs, buf, size))
return -EFAULT;
Expand Down Expand Up @@ -663,7 +636,7 @@ static int __init zcore_reipl_init(void)
if (ipib_info.ipib < ZFCPDUMP_HSA_SIZE)
rc = memcpy_hsa_kernel(ipl_block, ipib_info.ipib, PAGE_SIZE);
else
rc = memcpy_real(ipl_block, ipib_info.ipib, PAGE_SIZE);
rc = memcpy_real(ipl_block, (void *) ipib_info.ipib, PAGE_SIZE);
if (rc) {
free_page((unsigned long) ipl_block);
return rc;
Expand Down

0 comments on commit 92fe313

Please sign in to comment.