[PATCH] s390: add vmcp interface
Add interface to issue VM control program commands. Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
committed by
Linus Torvalds
parent
77fa22450d
commit
6b979de395
@ -2,7 +2,7 @@
|
||||
* arch/s390/kernel/cpcmd.c
|
||||
*
|
||||
* S390 version
|
||||
* Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
|
||||
* Copyright (C) 1999,2005 IBM Deutschland Entwicklung GmbH, IBM Corporation
|
||||
* Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
|
||||
* Christian Borntraeger (cborntra@de.ibm.com),
|
||||
*/
|
||||
@ -18,93 +18,114 @@
|
||||
#include <asm/system.h>
|
||||
|
||||
static DEFINE_SPINLOCK(cpcmd_lock);
|
||||
static char cpcmd_buf[240];
|
||||
static char cpcmd_buf[241];
|
||||
|
||||
/*
|
||||
* the caller of __cpcmd has to ensure that the response buffer is below 2 GB
|
||||
*/
|
||||
void __cpcmd(char *cmd, char *response, int rlen)
|
||||
int __cpcmd(const char *cmd, char *response, int rlen, int *response_code)
|
||||
{
|
||||
const int mask = 0x40000000L;
|
||||
unsigned long flags;
|
||||
int return_code;
|
||||
int return_len;
|
||||
int cmdlen;
|
||||
|
||||
spin_lock_irqsave(&cpcmd_lock, flags);
|
||||
cmdlen = strlen(cmd);
|
||||
BUG_ON(cmdlen > 240);
|
||||
strcpy(cpcmd_buf, cmd);
|
||||
memcpy(cpcmd_buf, cmd, cmdlen);
|
||||
ASCEBC(cpcmd_buf, cmdlen);
|
||||
|
||||
if (response != NULL && rlen > 0) {
|
||||
memset(response, 0, rlen);
|
||||
#ifndef CONFIG_ARCH_S390X
|
||||
asm volatile ("LRA 2,0(%0)\n\t"
|
||||
"LR 4,%1\n\t"
|
||||
"O 4,%4\n\t"
|
||||
"LRA 3,0(%2)\n\t"
|
||||
"LR 5,%3\n\t"
|
||||
".long 0x83240008 # Diagnose X'08'\n\t"
|
||||
: /* no output */
|
||||
: "a" (cpcmd_buf), "d" (cmdlen),
|
||||
"a" (response), "d" (rlen), "m" (mask)
|
||||
: "cc", "2", "3", "4", "5" );
|
||||
asm volatile ( "lra 2,0(%2)\n"
|
||||
"lr 4,%3\n"
|
||||
"o 4,%6\n"
|
||||
"lra 3,0(%4)\n"
|
||||
"lr 5,%5\n"
|
||||
"diag 2,4,0x8\n"
|
||||
"brc 8, .Litfits\n"
|
||||
"ar 5, %5\n"
|
||||
".Litfits: \n"
|
||||
"lr %0,4\n"
|
||||
"lr %1,5\n"
|
||||
: "=d" (return_code), "=d" (return_len)
|
||||
: "a" (cpcmd_buf), "d" (cmdlen),
|
||||
"a" (response), "d" (rlen), "m" (mask)
|
||||
: "cc", "2", "3", "4", "5" );
|
||||
#else /* CONFIG_ARCH_S390X */
|
||||
asm volatile (" lrag 2,0(%0)\n"
|
||||
" lgr 4,%1\n"
|
||||
" o 4,%4\n"
|
||||
" lrag 3,0(%2)\n"
|
||||
" lgr 5,%3\n"
|
||||
" sam31\n"
|
||||
" .long 0x83240008 # Diagnose X'08'\n"
|
||||
" sam64"
|
||||
: /* no output */
|
||||
: "a" (cpcmd_buf), "d" (cmdlen),
|
||||
"a" (response), "d" (rlen), "m" (mask)
|
||||
: "cc", "2", "3", "4", "5" );
|
||||
asm volatile ( "lrag 2,0(%2)\n"
|
||||
"lgr 4,%3\n"
|
||||
"o 4,%6\n"
|
||||
"lrag 3,0(%4)\n"
|
||||
"lgr 5,%5\n"
|
||||
"sam31\n"
|
||||
"diag 2,4,0x8\n"
|
||||
"sam64\n"
|
||||
"brc 8, .Litfits\n"
|
||||
"agr 5, %5\n"
|
||||
".Litfits: \n"
|
||||
"lgr %0,4\n"
|
||||
"lgr %1,5\n"
|
||||
: "=d" (return_code), "=d" (return_len)
|
||||
: "a" (cpcmd_buf), "d" (cmdlen),
|
||||
"a" (response), "d" (rlen), "m" (mask)
|
||||
: "cc", "2", "3", "4", "5" );
|
||||
#endif /* CONFIG_ARCH_S390X */
|
||||
EBCASC(response, rlen);
|
||||
} else {
|
||||
return_len = 0;
|
||||
#ifndef CONFIG_ARCH_S390X
|
||||
asm volatile ("LRA 2,0(%0)\n\t"
|
||||
"LR 3,%1\n\t"
|
||||
".long 0x83230008 # Diagnose X'08'\n\t"
|
||||
: /* no output */
|
||||
: "a" (cpcmd_buf), "d" (cmdlen)
|
||||
: "2", "3" );
|
||||
asm volatile ( "lra 2,0(%1)\n"
|
||||
"lr 3,%2\n"
|
||||
"diag 2,3,0x8\n"
|
||||
"lr %0,3\n"
|
||||
: "=d" (return_code)
|
||||
: "a" (cpcmd_buf), "d" (cmdlen)
|
||||
: "2", "3" );
|
||||
#else /* CONFIG_ARCH_S390X */
|
||||
asm volatile (" lrag 2,0(%0)\n"
|
||||
" lgr 3,%1\n"
|
||||
" sam31\n"
|
||||
" .long 0x83230008 # Diagnose X'08'\n"
|
||||
" sam64"
|
||||
: /* no output */
|
||||
: "a" (cpcmd_buf), "d" (cmdlen)
|
||||
: "2", "3" );
|
||||
asm volatile ( "lrag 2,0(%1)\n"
|
||||
"lgr 3,%2\n"
|
||||
"sam31\n"
|
||||
"diag 2,3,0x8\n"
|
||||
"sam64\n"
|
||||
"lgr %0,3\n"
|
||||
: "=d" (return_code)
|
||||
: "a" (cpcmd_buf), "d" (cmdlen)
|
||||
: "2", "3" );
|
||||
#endif /* CONFIG_ARCH_S390X */
|
||||
}
|
||||
spin_unlock_irqrestore(&cpcmd_lock, flags);
|
||||
if (response_code != NULL)
|
||||
*response_code = return_code;
|
||||
return return_len;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(__cpcmd);
|
||||
|
||||
#ifdef CONFIG_ARCH_S390X
|
||||
void cpcmd(char *cmd, char *response, int rlen)
|
||||
int cpcmd(const char *cmd, char *response, int rlen, int *response_code)
|
||||
{
|
||||
char *lowbuf;
|
||||
int len;
|
||||
|
||||
if ((rlen == 0) || (response == NULL)
|
||||
|| !((unsigned long)response >> 31))
|
||||
__cpcmd(cmd, response, rlen);
|
||||
len = __cpcmd(cmd, response, rlen, response_code);
|
||||
else {
|
||||
lowbuf = kmalloc(rlen, GFP_KERNEL | GFP_DMA);
|
||||
if (!lowbuf) {
|
||||
printk(KERN_WARNING
|
||||
"cpcmd: could not allocate response buffer\n");
|
||||
return;
|
||||
return -ENOMEM;
|
||||
}
|
||||
__cpcmd(cmd, lowbuf, rlen);
|
||||
len = __cpcmd(cmd, lowbuf, rlen, response_code);
|
||||
memcpy(response, lowbuf, rlen);
|
||||
kfree(lowbuf);
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(cpcmd);
|
||||
|
@ -198,11 +198,11 @@ static void __init conmode_default(void)
|
||||
char *ptr;
|
||||
|
||||
if (MACHINE_IS_VM) {
|
||||
__cpcmd("QUERY CONSOLE", query_buffer, 1024);
|
||||
__cpcmd("QUERY CONSOLE", query_buffer, 1024, NULL);
|
||||
console_devno = simple_strtoul(query_buffer + 5, NULL, 16);
|
||||
ptr = strstr(query_buffer, "SUBCHANNEL =");
|
||||
console_irq = simple_strtoul(ptr + 13, NULL, 16);
|
||||
__cpcmd("QUERY TERM", query_buffer, 1024);
|
||||
__cpcmd("QUERY TERM", query_buffer, 1024, NULL);
|
||||
ptr = strstr(query_buffer, "CONMODE");
|
||||
/*
|
||||
* Set the conmode to 3215 so that the device recognition
|
||||
@ -211,7 +211,7 @@ static void __init conmode_default(void)
|
||||
* 3215 and the 3270 driver will try to access the console
|
||||
* device (3215 as console and 3270 as normal tty).
|
||||
*/
|
||||
__cpcmd("TERM CONMODE 3215", NULL, 0);
|
||||
__cpcmd("TERM CONMODE 3215", NULL, 0, NULL);
|
||||
if (ptr == NULL) {
|
||||
#if defined(CONFIG_SCLP_CONSOLE)
|
||||
SET_CONSOLE_SCLP;
|
||||
|
@ -284,7 +284,7 @@ static void do_machine_restart(void * __unused)
|
||||
* locks are always held disabled).
|
||||
*/
|
||||
if (MACHINE_IS_VM)
|
||||
cpcmd ("IPL", NULL, 0);
|
||||
cpcmd ("IPL", NULL, 0, NULL);
|
||||
else
|
||||
reipl (0x10000 | S390_lowcore.ipl_device);
|
||||
}
|
||||
@ -313,7 +313,7 @@ static void do_machine_halt(void * __unused)
|
||||
if (atomic_compare_and_swap(-1, smp_processor_id(), &cpuid) == 0) {
|
||||
smp_send_stop();
|
||||
if (MACHINE_IS_VM && strlen(vmhalt_cmd) > 0)
|
||||
cpcmd(vmhalt_cmd, NULL, 0);
|
||||
cpcmd(vmhalt_cmd, NULL, 0, NULL);
|
||||
signal_processor(smp_processor_id(),
|
||||
sigp_stop_and_store_status);
|
||||
}
|
||||
@ -332,7 +332,7 @@ static void do_machine_power_off(void * __unused)
|
||||
if (atomic_compare_and_swap(-1, smp_processor_id(), &cpuid) == 0) {
|
||||
smp_send_stop();
|
||||
if (MACHINE_IS_VM && strlen(vmpoff_cmd) > 0)
|
||||
cpcmd(vmpoff_cmd, NULL, 0);
|
||||
cpcmd(vmpoff_cmd, NULL, 0, NULL);
|
||||
signal_processor(smp_processor_id(),
|
||||
sigp_stop_and_store_status);
|
||||
}
|
||||
|
@ -735,7 +735,7 @@ void __init trap_init(void)
|
||||
&ext_int_pfault);
|
||||
#endif
|
||||
#ifndef CONFIG_ARCH_S390X
|
||||
cpcmd("SET PAGEX ON", NULL, 0);
|
||||
cpcmd("SET PAGEX ON", NULL, 0, NULL);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user