All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC] [PATCH] Write to HVC terminal from purgatory code
@ 2009-09-07  5:14 ` M. Mohan Kumar
  0 siblings, 0 replies; 8+ messages in thread
From: M. Mohan Kumar @ 2009-09-07  5:14 UTC (permalink / raw)
  To: horms, kexec; +Cc: linuxppc-dev, miltonm

Write to HVC terminal from purgatory code

Current x86/x86-64 kexec-tools print the message "I'm in purgatory" to
serial console/VGA while executing the purgatory code.  Implement this
feature for POWERPC pseries platform by using the H_PUT_TERM_CHAR
hypervisor call by printng to hvc console.


Signed-off-by: M. Mohan Kumar <mohan@in.ibm.com>
---
 kexec/arch/ppc64/fs2dt.c               |   47 +++++++++++++++++++++++++++++++-
 kexec/arch/ppc64/kexec-elf-ppc64.c     |    7 +++++
 kexec/arch/ppc64/kexec-ppc64.h         |    1 +
 purgatory/arch/ppc64/Makefile          |    1 +
 purgatory/arch/ppc64/console-ppc64.c   |   14 +++++++++
 purgatory/arch/ppc64/hvCall.S          |   28 +++++++++++++++++++
 purgatory/arch/ppc64/hvCall.h          |    8 +++++
 purgatory/arch/ppc64/purgatory-ppc64.c |    1 +
 8 files changed, 106 insertions(+), 1 deletions(-)
 create mode 100644 purgatory/arch/ppc64/hvCall.S
 create mode 100644 purgatory/arch/ppc64/hvCall.h

diff --git a/kexec/arch/ppc64/fs2dt.c b/kexec/arch/ppc64/fs2dt.c
index b01ff86..bd9d36c 100644
--- a/kexec/arch/ppc64/fs2dt.c
+++ b/kexec/arch/ppc64/fs2dt.c
@@ -434,6 +434,9 @@ static void putnode(void)
 	if (!strcmp(basename,"/chosen/")) {
 		size_t cmd_len = 0;
 		char *param = NULL;
+		char filename[MAXPATH];
+		char buff[64];
+		int fd;
 
 		cmd_len = strlen(local_cmdline);
 		if (cmd_len != 0) {
@@ -446,7 +449,6 @@ static void putnode(void)
 
 		/* ... if not, grab root= from the old command line */
 		if (!param) {
-			char filename[MAXPATH];
 			FILE *fp;
 			char *last_cmdline = NULL;
 			char *old_param;
@@ -483,8 +485,51 @@ static void putnode(void)
 		dt += (cmd_len + 3)/4;
 
 		fprintf(stderr, "Modified cmdline:%s\n", local_cmdline);
+
+		/*
+		 * Determine the platform type/stdout type, so that purgatory
+		 * code can print 'I'm in purgatory' message. Currently only
+		 * pseries/hvcterminal is supported.
+		 */
+		strcpy(filename, pathname);
+		strcat(filename, "linux,stdout-path");
+		fd = open(filename, O_RDONLY);
+		if (fd == -1) {
+			printf("Unable to find linux,stdout-path, printing"
+					" from purgatory is diabled\n");
+			goto no_debug;
+		}
+		if (fstat(fd, &statbuf)) {
+			printf("Unable to stat linux,stdout-path, printing"
+					" from purgatory is diabled\n");
+			close(fd);
+			goto no_debug;
+		}
+		read(fd, buff, statbuf.st_size);
+		close(fd);
+		strcpy(filename, "/proc/device-tree/");
+		strcat(filename, buff);
+		strcat(filename, "/compatible");
+		fd = open(filename, O_RDONLY);
+		if (fd == -1) {
+			printf("Unable to find linux,stdout-path/compatible, "
+				" printing from purgatory is diabled\n");
+			goto no_debug;
+		}
+		if (fstat(fd, &statbuf)) {
+			printf("Unable to stat linux,stdout-path/compatible, "
+				" printing from purgatory is diabled\n");
+			close(fd);
+			goto no_debug;
+		}
+		read(fd, buff, statbuf.st_size);
+		if (!strcmp(buff, "hvterm1") ||
+					!strcmp(buff, "hvterm-protocol"))
+			my_debug = 1;
+		close(fd);
 	}
 
+no_debug:
 	for (i=0; i < numlist; i++) {
 		dp = namelist[i];
 		strcpy(dn, dp->d_name);
diff --git a/kexec/arch/ppc64/kexec-elf-ppc64.c b/kexec/arch/ppc64/kexec-elf-ppc64.c
index 21533cb..65fc42f 100644
--- a/kexec/arch/ppc64/kexec-elf-ppc64.c
+++ b/kexec/arch/ppc64/kexec-elf-ppc64.c
@@ -41,6 +41,8 @@
 uint64_t initrd_base, initrd_size;
 unsigned char reuse_initrd = 0;
 const char *ramdisk;
+/* Used for enabling printing message from purgatory code */
+int my_debug = 0;
 
 int elf_ppc64_probe(const char *buf, off_t len)
 {
@@ -296,6 +298,8 @@ int elf_ppc64_load(int argc, char **argv, const char *buf, off_t len,
 	toc_addr = my_r2(&info->rhdr);
 	elf_rel_set_symbol(&info->rhdr, "my_toc", &toc_addr, sizeof(toc_addr));
 
+	/* Set debug */
+	elf_rel_set_symbol(&info->rhdr, "debug", &my_debug, sizeof(my_debug));
 #ifdef DEBUG
 	my_kernel = 0;
 	my_dt_offset = 0;
@@ -304,6 +308,7 @@ int elf_ppc64_load(int argc, char **argv, const char *buf, off_t len,
 	my_stack = 0;
 	toc_addr = 0;
 	my_run_at_load = 0;
+	my_debug = 0;
 
 	elf_rel_get_symbol(&info->rhdr, "kernel", &my_kernel, sizeof(my_kernel));
 	elf_rel_get_symbol(&info->rhdr, "dt_offset", &my_dt_offset,
@@ -317,6 +322,7 @@ int elf_ppc64_load(int argc, char **argv, const char *buf, off_t len,
 	elf_rel_get_symbol(&info->rhdr, "stack", &my_stack, sizeof(my_stack));
 	elf_rel_get_symbol(&info->rhdr, "my_toc", &toc_addr,
 				sizeof(toc_addr));
+	elf_rel_get_symbol(&info->rhdr, "debug", &my_debug, sizeof(my_debug));
 
 	fprintf(stderr, "info->entry is %p\n", info->entry);
 	fprintf(stderr, "kernel is %llx\n", (unsigned long long)my_kernel);
@@ -329,6 +335,7 @@ int elf_ppc64_load(int argc, char **argv, const char *buf, off_t len,
 	fprintf(stderr, "stack is %llx\n", (unsigned long long)my_stack);
 	fprintf(stderr, "toc_addr is %llx\n", (unsigned long long)toc_addr);
 	fprintf(stderr, "purgatory size is %zu\n", purgatory_size);
+	fprintf(stderr, "debug is %d\n", my_debug);
 #endif
 
 	for (i = 0; i < info->nr_segments; i++)
diff --git a/kexec/arch/ppc64/kexec-ppc64.h b/kexec/arch/ppc64/kexec-ppc64.h
index 920ac46..838c6da 100644
--- a/kexec/arch/ppc64/kexec-ppc64.h
+++ b/kexec/arch/ppc64/kexec-ppc64.h
@@ -20,6 +20,7 @@ unsigned long my_r2(const struct mem_ehdr *ehdr);
 extern uint64_t initrd_base, initrd_size;
 extern int max_memory_ranges;
 extern unsigned char reuse_initrd;
+extern int my_debug;
 
 /* boot block version 2 as defined by the linux kernel */
 struct bootblock {
diff --git a/purgatory/arch/ppc64/Makefile b/purgatory/arch/ppc64/Makefile
index aaa4046..40a9e99 100644
--- a/purgatory/arch/ppc64/Makefile
+++ b/purgatory/arch/ppc64/Makefile
@@ -3,6 +3,7 @@
 #
 
 ppc64_PURGATORY_SRCS += purgatory/arch/ppc64/v2wrap.S
+ppc64_PURGATORY_SRCS += purgatory/arch/ppc64/hvCall.S
 ppc64_PURGATORY_SRCS += purgatory/arch/ppc64/purgatory-ppc64.c
 ppc64_PURGATORY_SRCS += purgatory/arch/ppc64/console-ppc64.c
 ppc64_PURGATORY_SRCS += purgatory/arch/ppc64/crashdump_backup.c
diff --git a/purgatory/arch/ppc64/console-ppc64.c b/purgatory/arch/ppc64/console-ppc64.c
index d6da7b3..78a233b 100644
--- a/purgatory/arch/ppc64/console-ppc64.c
+++ b/purgatory/arch/ppc64/console-ppc64.c
@@ -20,8 +20,22 @@
  */
 
 #include <purgatory.h>
+#include "hvCall.h"
+
+extern int debug;
 
 void putchar(int c)
 {
+	char buff[16];
+	unsigned long *lbuf = (unsigned long *)buff;
+
+	if (!debug) /* running on non pseries */
+		return;
+
+	if (c == '\n')
+		putchar('\r');
+
+	buff[0] = c;
+	plpar_hcall_norets(H_PUT_TERM_CHAR, 0, 1, lbuf[0], lbuf[1]);
 	return;
 }
diff --git a/purgatory/arch/ppc64/hvCall.S b/purgatory/arch/ppc64/hvCall.S
new file mode 100644
index 0000000..e401f81
--- /dev/null
+++ b/purgatory/arch/ppc64/hvCall.S
@@ -0,0 +1,28 @@
+/*
+ * This file contains the generic function to perform a call to the
+ * pSeries LPAR hypervisor.
+ *
+ * Created by M. Mohan Kumar (mohan@in.ibm.com)
+ * Copyright (C) IBM Corporation
+ * Taken from linux/arch/powerpc/platforms/pseries/hvCall.S
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#define HVSC	.long 0x44000022
+.text
+	.machine ppc64
+.globl .plpar_hcall_norets
+.plpar_hcall_norets:
+	or	6,6,6			# medium low priority
+        mfcr	0
+        stw	0,8(1)
+
+        HVSC 				/* invoke the hypervisor */
+
+        lwz	0,8(1)
+        mtcrf	0xff,0
+        blr                             /* return r3 = status */
diff --git a/purgatory/arch/ppc64/hvCall.h b/purgatory/arch/ppc64/hvCall.h
new file mode 100644
index 0000000..187e24d
--- /dev/null
+++ b/purgatory/arch/ppc64/hvCall.h
@@ -0,0 +1,8 @@
+#ifndef HVCALL_H
+#define HVCALL_H
+
+#define H_PUT_TERM_CHAR	0x58
+
+long plpar_hcall_norets(unsigned long opcode, ...);
+
+#endif
diff --git a/purgatory/arch/ppc64/purgatory-ppc64.c b/purgatory/arch/ppc64/purgatory-ppc64.c
index 93f28d2..0b6d326 100644
--- a/purgatory/arch/ppc64/purgatory-ppc64.c
+++ b/purgatory/arch/ppc64/purgatory-ppc64.c
@@ -28,6 +28,7 @@ unsigned long stack = 0;
 unsigned long dt_offset = 0;
 unsigned long my_toc = 0;
 unsigned long kernel = 0;
+unsigned int debug = 0;
 
 void setup_arch(void)
 {
-- 
1.6.2.5

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [RFC] [PATCH] Write to HVC terminal from purgatory code
@ 2009-09-07  5:14 ` M. Mohan Kumar
  0 siblings, 0 replies; 8+ messages in thread
From: M. Mohan Kumar @ 2009-09-07  5:14 UTC (permalink / raw)
  To: horms, kexec; +Cc: linuxppc-dev, miltonm

Write to HVC terminal from purgatory code

Current x86/x86-64 kexec-tools print the message "I'm in purgatory" to
serial console/VGA while executing the purgatory code.  Implement this
feature for POWERPC pseries platform by using the H_PUT_TERM_CHAR
hypervisor call by printng to hvc console.


Signed-off-by: M. Mohan Kumar <mohan@in.ibm.com>
---
 kexec/arch/ppc64/fs2dt.c               |   47 +++++++++++++++++++++++++++++++-
 kexec/arch/ppc64/kexec-elf-ppc64.c     |    7 +++++
 kexec/arch/ppc64/kexec-ppc64.h         |    1 +
 purgatory/arch/ppc64/Makefile          |    1 +
 purgatory/arch/ppc64/console-ppc64.c   |   14 +++++++++
 purgatory/arch/ppc64/hvCall.S          |   28 +++++++++++++++++++
 purgatory/arch/ppc64/hvCall.h          |    8 +++++
 purgatory/arch/ppc64/purgatory-ppc64.c |    1 +
 8 files changed, 106 insertions(+), 1 deletions(-)
 create mode 100644 purgatory/arch/ppc64/hvCall.S
 create mode 100644 purgatory/arch/ppc64/hvCall.h

diff --git a/kexec/arch/ppc64/fs2dt.c b/kexec/arch/ppc64/fs2dt.c
index b01ff86..bd9d36c 100644
--- a/kexec/arch/ppc64/fs2dt.c
+++ b/kexec/arch/ppc64/fs2dt.c
@@ -434,6 +434,9 @@ static void putnode(void)
 	if (!strcmp(basename,"/chosen/")) {
 		size_t cmd_len = 0;
 		char *param = NULL;
+		char filename[MAXPATH];
+		char buff[64];
+		int fd;
 
 		cmd_len = strlen(local_cmdline);
 		if (cmd_len != 0) {
@@ -446,7 +449,6 @@ static void putnode(void)
 
 		/* ... if not, grab root= from the old command line */
 		if (!param) {
-			char filename[MAXPATH];
 			FILE *fp;
 			char *last_cmdline = NULL;
 			char *old_param;
@@ -483,8 +485,51 @@ static void putnode(void)
 		dt += (cmd_len + 3)/4;
 
 		fprintf(stderr, "Modified cmdline:%s\n", local_cmdline);
+
+		/*
+		 * Determine the platform type/stdout type, so that purgatory
+		 * code can print 'I'm in purgatory' message. Currently only
+		 * pseries/hvcterminal is supported.
+		 */
+		strcpy(filename, pathname);
+		strcat(filename, "linux,stdout-path");
+		fd = open(filename, O_RDONLY);
+		if (fd == -1) {
+			printf("Unable to find linux,stdout-path, printing"
+					" from purgatory is diabled\n");
+			goto no_debug;
+		}
+		if (fstat(fd, &statbuf)) {
+			printf("Unable to stat linux,stdout-path, printing"
+					" from purgatory is diabled\n");
+			close(fd);
+			goto no_debug;
+		}
+		read(fd, buff, statbuf.st_size);
+		close(fd);
+		strcpy(filename, "/proc/device-tree/");
+		strcat(filename, buff);
+		strcat(filename, "/compatible");
+		fd = open(filename, O_RDONLY);
+		if (fd == -1) {
+			printf("Unable to find linux,stdout-path/compatible, "
+				" printing from purgatory is diabled\n");
+			goto no_debug;
+		}
+		if (fstat(fd, &statbuf)) {
+			printf("Unable to stat linux,stdout-path/compatible, "
+				" printing from purgatory is diabled\n");
+			close(fd);
+			goto no_debug;
+		}
+		read(fd, buff, statbuf.st_size);
+		if (!strcmp(buff, "hvterm1") ||
+					!strcmp(buff, "hvterm-protocol"))
+			my_debug = 1;
+		close(fd);
 	}
 
+no_debug:
 	for (i=0; i < numlist; i++) {
 		dp = namelist[i];
 		strcpy(dn, dp->d_name);
diff --git a/kexec/arch/ppc64/kexec-elf-ppc64.c b/kexec/arch/ppc64/kexec-elf-ppc64.c
index 21533cb..65fc42f 100644
--- a/kexec/arch/ppc64/kexec-elf-ppc64.c
+++ b/kexec/arch/ppc64/kexec-elf-ppc64.c
@@ -41,6 +41,8 @@
 uint64_t initrd_base, initrd_size;
 unsigned char reuse_initrd = 0;
 const char *ramdisk;
+/* Used for enabling printing message from purgatory code */
+int my_debug = 0;
 
 int elf_ppc64_probe(const char *buf, off_t len)
 {
@@ -296,6 +298,8 @@ int elf_ppc64_load(int argc, char **argv, const char *buf, off_t len,
 	toc_addr = my_r2(&info->rhdr);
 	elf_rel_set_symbol(&info->rhdr, "my_toc", &toc_addr, sizeof(toc_addr));
 
+	/* Set debug */
+	elf_rel_set_symbol(&info->rhdr, "debug", &my_debug, sizeof(my_debug));
 #ifdef DEBUG
 	my_kernel = 0;
 	my_dt_offset = 0;
@@ -304,6 +308,7 @@ int elf_ppc64_load(int argc, char **argv, const char *buf, off_t len,
 	my_stack = 0;
 	toc_addr = 0;
 	my_run_at_load = 0;
+	my_debug = 0;
 
 	elf_rel_get_symbol(&info->rhdr, "kernel", &my_kernel, sizeof(my_kernel));
 	elf_rel_get_symbol(&info->rhdr, "dt_offset", &my_dt_offset,
@@ -317,6 +322,7 @@ int elf_ppc64_load(int argc, char **argv, const char *buf, off_t len,
 	elf_rel_get_symbol(&info->rhdr, "stack", &my_stack, sizeof(my_stack));
 	elf_rel_get_symbol(&info->rhdr, "my_toc", &toc_addr,
 				sizeof(toc_addr));
+	elf_rel_get_symbol(&info->rhdr, "debug", &my_debug, sizeof(my_debug));
 
 	fprintf(stderr, "info->entry is %p\n", info->entry);
 	fprintf(stderr, "kernel is %llx\n", (unsigned long long)my_kernel);
@@ -329,6 +335,7 @@ int elf_ppc64_load(int argc, char **argv, const char *buf, off_t len,
 	fprintf(stderr, "stack is %llx\n", (unsigned long long)my_stack);
 	fprintf(stderr, "toc_addr is %llx\n", (unsigned long long)toc_addr);
 	fprintf(stderr, "purgatory size is %zu\n", purgatory_size);
+	fprintf(stderr, "debug is %d\n", my_debug);
 #endif
 
 	for (i = 0; i < info->nr_segments; i++)
diff --git a/kexec/arch/ppc64/kexec-ppc64.h b/kexec/arch/ppc64/kexec-ppc64.h
index 920ac46..838c6da 100644
--- a/kexec/arch/ppc64/kexec-ppc64.h
+++ b/kexec/arch/ppc64/kexec-ppc64.h
@@ -20,6 +20,7 @@ unsigned long my_r2(const struct mem_ehdr *ehdr);
 extern uint64_t initrd_base, initrd_size;
 extern int max_memory_ranges;
 extern unsigned char reuse_initrd;
+extern int my_debug;
 
 /* boot block version 2 as defined by the linux kernel */
 struct bootblock {
diff --git a/purgatory/arch/ppc64/Makefile b/purgatory/arch/ppc64/Makefile
index aaa4046..40a9e99 100644
--- a/purgatory/arch/ppc64/Makefile
+++ b/purgatory/arch/ppc64/Makefile
@@ -3,6 +3,7 @@
 #
 
 ppc64_PURGATORY_SRCS += purgatory/arch/ppc64/v2wrap.S
+ppc64_PURGATORY_SRCS += purgatory/arch/ppc64/hvCall.S
 ppc64_PURGATORY_SRCS += purgatory/arch/ppc64/purgatory-ppc64.c
 ppc64_PURGATORY_SRCS += purgatory/arch/ppc64/console-ppc64.c
 ppc64_PURGATORY_SRCS += purgatory/arch/ppc64/crashdump_backup.c
diff --git a/purgatory/arch/ppc64/console-ppc64.c b/purgatory/arch/ppc64/console-ppc64.c
index d6da7b3..78a233b 100644
--- a/purgatory/arch/ppc64/console-ppc64.c
+++ b/purgatory/arch/ppc64/console-ppc64.c
@@ -20,8 +20,22 @@
  */
 
 #include <purgatory.h>
+#include "hvCall.h"
+
+extern int debug;
 
 void putchar(int c)
 {
+	char buff[16];
+	unsigned long *lbuf = (unsigned long *)buff;
+
+	if (!debug) /* running on non pseries */
+		return;
+
+	if (c == '\n')
+		putchar('\r');
+
+	buff[0] = c;
+	plpar_hcall_norets(H_PUT_TERM_CHAR, 0, 1, lbuf[0], lbuf[1]);
 	return;
 }
diff --git a/purgatory/arch/ppc64/hvCall.S b/purgatory/arch/ppc64/hvCall.S
new file mode 100644
index 0000000..e401f81
--- /dev/null
+++ b/purgatory/arch/ppc64/hvCall.S
@@ -0,0 +1,28 @@
+/*
+ * This file contains the generic function to perform a call to the
+ * pSeries LPAR hypervisor.
+ *
+ * Created by M. Mohan Kumar (mohan@in.ibm.com)
+ * Copyright (C) IBM Corporation
+ * Taken from linux/arch/powerpc/platforms/pseries/hvCall.S
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#define HVSC	.long 0x44000022
+.text
+	.machine ppc64
+.globl .plpar_hcall_norets
+.plpar_hcall_norets:
+	or	6,6,6			# medium low priority
+        mfcr	0
+        stw	0,8(1)
+
+        HVSC 				/* invoke the hypervisor */
+
+        lwz	0,8(1)
+        mtcrf	0xff,0
+        blr                             /* return r3 = status */
diff --git a/purgatory/arch/ppc64/hvCall.h b/purgatory/arch/ppc64/hvCall.h
new file mode 100644
index 0000000..187e24d
--- /dev/null
+++ b/purgatory/arch/ppc64/hvCall.h
@@ -0,0 +1,8 @@
+#ifndef HVCALL_H
+#define HVCALL_H
+
+#define H_PUT_TERM_CHAR	0x58
+
+long plpar_hcall_norets(unsigned long opcode, ...);
+
+#endif
diff --git a/purgatory/arch/ppc64/purgatory-ppc64.c b/purgatory/arch/ppc64/purgatory-ppc64.c
index 93f28d2..0b6d326 100644
--- a/purgatory/arch/ppc64/purgatory-ppc64.c
+++ b/purgatory/arch/ppc64/purgatory-ppc64.c
@@ -28,6 +28,7 @@ unsigned long stack = 0;
 unsigned long dt_offset = 0;
 unsigned long my_toc = 0;
 unsigned long kernel = 0;
+unsigned int debug = 0;
 
 void setup_arch(void)
 {
-- 
1.6.2.5


_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [RFC] [PATCH] Write to HVC terminal from purgatory code
  2009-09-07  5:14 ` M. Mohan Kumar
@ 2009-09-08 23:09   ` Simon Horman
  -1 siblings, 0 replies; 8+ messages in thread
From: Simon Horman @ 2009-09-08 23:09 UTC (permalink / raw)
  To: M. Mohan Kumar; +Cc: linuxppc-dev, kexec, miltonm

On Mon, Sep 07, 2009 at 10:44:07AM +0530, M. Mohan Kumar wrote:
> Write to HVC terminal from purgatory code
> 
> Current x86/x86-64 kexec-tools print the message "I'm in purgatory" to
> serial console/VGA while executing the purgatory code.  Implement this
> feature for POWERPC pseries platform by using the H_PUT_TERM_CHAR
> hypervisor call by printng to hvc console.

This change seems reasonable to me, can any of the ppc people offer a review?

> Signed-off-by: M. Mohan Kumar <mohan@in.ibm.com>
> ---
>  kexec/arch/ppc64/fs2dt.c               |   47 +++++++++++++++++++++++++++++++-
>  kexec/arch/ppc64/kexec-elf-ppc64.c     |    7 +++++
>  kexec/arch/ppc64/kexec-ppc64.h         |    1 +
>  purgatory/arch/ppc64/Makefile          |    1 +
>  purgatory/arch/ppc64/console-ppc64.c   |   14 +++++++++
>  purgatory/arch/ppc64/hvCall.S          |   28 +++++++++++++++++++
>  purgatory/arch/ppc64/hvCall.h          |    8 +++++
>  purgatory/arch/ppc64/purgatory-ppc64.c |    1 +
>  8 files changed, 106 insertions(+), 1 deletions(-)
>  create mode 100644 purgatory/arch/ppc64/hvCall.S
>  create mode 100644 purgatory/arch/ppc64/hvCall.h
> 
> diff --git a/kexec/arch/ppc64/fs2dt.c b/kexec/arch/ppc64/fs2dt.c
> index b01ff86..bd9d36c 100644
> --- a/kexec/arch/ppc64/fs2dt.c
> +++ b/kexec/arch/ppc64/fs2dt.c
> @@ -434,6 +434,9 @@ static void putnode(void)
>  	if (!strcmp(basename,"/chosen/")) {
>  		size_t cmd_len = 0;
>  		char *param = NULL;
> +		char filename[MAXPATH];
> +		char buff[64];

                Is always 64 big enough?
		It seems a bit arbitrary.

> +		int fd;
>  
>  		cmd_len = strlen(local_cmdline);
>  		if (cmd_len != 0) {
> @@ -446,7 +449,6 @@ static void putnode(void)
>  
>  		/* ... if not, grab root= from the old command line */
>  		if (!param) {
> -			char filename[MAXPATH];
>  			FILE *fp;
>  			char *last_cmdline = NULL;
>  			char *old_param;
> @@ -483,8 +485,51 @@ static void putnode(void)
>  		dt += (cmd_len + 3)/4;
>  
>  		fprintf(stderr, "Modified cmdline:%s\n", local_cmdline);
> +
> +		/*
> +		 * Determine the platform type/stdout type, so that purgatory
> +		 * code can print 'I'm in purgatory' message. Currently only
> +		 * pseries/hvcterminal is supported.
> +		 */
> +		strcpy(filename, pathname);
> +		strcat(filename, "linux,stdout-path");
> +		fd = open(filename, O_RDONLY);
> +		if (fd == -1) {
> +			printf("Unable to find linux,stdout-path, printing"
> +					" from purgatory is diabled\n");
> +			goto no_debug;
> +		}
> +		if (fstat(fd, &statbuf)) {
> +			printf("Unable to stat linux,stdout-path, printing"
> +					" from purgatory is diabled\n");
> +			close(fd);
> +			goto no_debug;
> +		}
> +		read(fd, buff, statbuf.st_size);
> +		close(fd);
> +		strcpy(filename, "/proc/device-tree/");
> +		strcat(filename, buff);
> +		strcat(filename, "/compatible");
> +		fd = open(filename, O_RDONLY);
> +		if (fd == -1) {
> +			printf("Unable to find linux,stdout-path/compatible, "
> +				" printing from purgatory is diabled\n");
> +			goto no_debug;
> +		}
> +		if (fstat(fd, &statbuf)) {
> +			printf("Unable to stat linux,stdout-path/compatible, "
> +				" printing from purgatory is diabled\n");
> +			close(fd);
> +			goto no_debug;
> +		}
> +		read(fd, buff, statbuf.st_size);
> +		if (!strcmp(buff, "hvterm1") ||
> +					!strcmp(buff, "hvterm-protocol"))
> +			my_debug = 1;
> +		close(fd);
>  	}
>  
> +no_debug:
>  	for (i=0; i < numlist; i++) {
>  		dp = namelist[i];
>  		strcpy(dn, dp->d_name);
> diff --git a/kexec/arch/ppc64/kexec-elf-ppc64.c b/kexec/arch/ppc64/kexec-elf-ppc64.c
> index 21533cb..65fc42f 100644
> --- a/kexec/arch/ppc64/kexec-elf-ppc64.c
> +++ b/kexec/arch/ppc64/kexec-elf-ppc64.c
> @@ -41,6 +41,8 @@
>  uint64_t initrd_base, initrd_size;
>  unsigned char reuse_initrd = 0;
>  const char *ramdisk;
> +/* Used for enabling printing message from purgatory code */
> +int my_debug = 0;
>  
>  int elf_ppc64_probe(const char *buf, off_t len)
>  {
> @@ -296,6 +298,8 @@ int elf_ppc64_load(int argc, char **argv, const char *buf, off_t len,
>  	toc_addr = my_r2(&info->rhdr);
>  	elf_rel_set_symbol(&info->rhdr, "my_toc", &toc_addr, sizeof(toc_addr));
>  
> +	/* Set debug */
> +	elf_rel_set_symbol(&info->rhdr, "debug", &my_debug, sizeof(my_debug));
>  #ifdef DEBUG
>  	my_kernel = 0;
>  	my_dt_offset = 0;
> @@ -304,6 +308,7 @@ int elf_ppc64_load(int argc, char **argv, const char *buf, off_t len,
>  	my_stack = 0;
>  	toc_addr = 0;
>  	my_run_at_load = 0;
> +	my_debug = 0;
>  
>  	elf_rel_get_symbol(&info->rhdr, "kernel", &my_kernel, sizeof(my_kernel));
>  	elf_rel_get_symbol(&info->rhdr, "dt_offset", &my_dt_offset,
> @@ -317,6 +322,7 @@ int elf_ppc64_load(int argc, char **argv, const char *buf, off_t len,
>  	elf_rel_get_symbol(&info->rhdr, "stack", &my_stack, sizeof(my_stack));
>  	elf_rel_get_symbol(&info->rhdr, "my_toc", &toc_addr,
>  				sizeof(toc_addr));
> +	elf_rel_get_symbol(&info->rhdr, "debug", &my_debug, sizeof(my_debug));
>  
>  	fprintf(stderr, "info->entry is %p\n", info->entry);
>  	fprintf(stderr, "kernel is %llx\n", (unsigned long long)my_kernel);
> @@ -329,6 +335,7 @@ int elf_ppc64_load(int argc, char **argv, const char *buf, off_t len,
>  	fprintf(stderr, "stack is %llx\n", (unsigned long long)my_stack);
>  	fprintf(stderr, "toc_addr is %llx\n", (unsigned long long)toc_addr);
>  	fprintf(stderr, "purgatory size is %zu\n", purgatory_size);
> +	fprintf(stderr, "debug is %d\n", my_debug);
>  #endif
>  
>  	for (i = 0; i < info->nr_segments; i++)
> diff --git a/kexec/arch/ppc64/kexec-ppc64.h b/kexec/arch/ppc64/kexec-ppc64.h
> index 920ac46..838c6da 100644
> --- a/kexec/arch/ppc64/kexec-ppc64.h
> +++ b/kexec/arch/ppc64/kexec-ppc64.h
> @@ -20,6 +20,7 @@ unsigned long my_r2(const struct mem_ehdr *ehdr);
>  extern uint64_t initrd_base, initrd_size;
>  extern int max_memory_ranges;
>  extern unsigned char reuse_initrd;
> +extern int my_debug;
>  
>  /* boot block version 2 as defined by the linux kernel */
>  struct bootblock {
> diff --git a/purgatory/arch/ppc64/Makefile b/purgatory/arch/ppc64/Makefile
> index aaa4046..40a9e99 100644
> --- a/purgatory/arch/ppc64/Makefile
> +++ b/purgatory/arch/ppc64/Makefile
> @@ -3,6 +3,7 @@
>  #
>  
>  ppc64_PURGATORY_SRCS += purgatory/arch/ppc64/v2wrap.S
> +ppc64_PURGATORY_SRCS += purgatory/arch/ppc64/hvCall.S
>  ppc64_PURGATORY_SRCS += purgatory/arch/ppc64/purgatory-ppc64.c
>  ppc64_PURGATORY_SRCS += purgatory/arch/ppc64/console-ppc64.c
>  ppc64_PURGATORY_SRCS += purgatory/arch/ppc64/crashdump_backup.c
> diff --git a/purgatory/arch/ppc64/console-ppc64.c b/purgatory/arch/ppc64/console-ppc64.c
> index d6da7b3..78a233b 100644
> --- a/purgatory/arch/ppc64/console-ppc64.c
> +++ b/purgatory/arch/ppc64/console-ppc64.c
> @@ -20,8 +20,22 @@
>   */
>  
>  #include <purgatory.h>
> +#include "hvCall.h"
> +
> +extern int debug;
>  
>  void putchar(int c)
>  {
> +	char buff[16];
> +	unsigned long *lbuf = (unsigned long *)buff;
> +
> +	if (!debug) /* running on non pseries */
> +		return;
> +
> +	if (c == '\n')
> +		putchar('\r');
> +
> +	buff[0] = c;
> +	plpar_hcall_norets(H_PUT_TERM_CHAR, 0, 1, lbuf[0], lbuf[1]);
>  	return;
>  }
> diff --git a/purgatory/arch/ppc64/hvCall.S b/purgatory/arch/ppc64/hvCall.S
> new file mode 100644
> index 0000000..e401f81
> --- /dev/null
> +++ b/purgatory/arch/ppc64/hvCall.S
> @@ -0,0 +1,28 @@
> +/*
> + * This file contains the generic function to perform a call to the
> + * pSeries LPAR hypervisor.
> + *
> + * Created by M. Mohan Kumar (mohan@in.ibm.com)
> + * Copyright (C) IBM Corporation
> + * Taken from linux/arch/powerpc/platforms/pseries/hvCall.S
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License
> + * as published by the Free Software Foundation; either version
> + * 2 of the License, or (at your option) any later version.
> + */
> +
> +#define HVSC	.long 0x44000022
> +.text
> +	.machine ppc64
> +.globl .plpar_hcall_norets
> +.plpar_hcall_norets:
> +	or	6,6,6			# medium low priority
> +        mfcr	0
> +        stw	0,8(1)
> +
> +        HVSC 				/* invoke the hypervisor */
> +
> +        lwz	0,8(1)
> +        mtcrf	0xff,0
> +        blr                             /* return r3 = status */
> diff --git a/purgatory/arch/ppc64/hvCall.h b/purgatory/arch/ppc64/hvCall.h
> new file mode 100644
> index 0000000..187e24d
> --- /dev/null
> +++ b/purgatory/arch/ppc64/hvCall.h
> @@ -0,0 +1,8 @@
> +#ifndef HVCALL_H
> +#define HVCALL_H
> +
> +#define H_PUT_TERM_CHAR	0x58
> +
> +long plpar_hcall_norets(unsigned long opcode, ...);
> +
> +#endif
> diff --git a/purgatory/arch/ppc64/purgatory-ppc64.c b/purgatory/arch/ppc64/purgatory-ppc64.c
> index 93f28d2..0b6d326 100644
> --- a/purgatory/arch/ppc64/purgatory-ppc64.c
> +++ b/purgatory/arch/ppc64/purgatory-ppc64.c
> @@ -28,6 +28,7 @@ unsigned long stack = 0;
>  unsigned long dt_offset = 0;
>  unsigned long my_toc = 0;
>  unsigned long kernel = 0;
> +unsigned int debug = 0;
>  
>  void setup_arch(void)
>  {
> -- 
> 1.6.2.5

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [RFC] [PATCH] Write to HVC terminal from purgatory code
@ 2009-09-08 23:09   ` Simon Horman
  0 siblings, 0 replies; 8+ messages in thread
From: Simon Horman @ 2009-09-08 23:09 UTC (permalink / raw)
  To: M. Mohan Kumar; +Cc: linuxppc-dev, kexec, miltonm

On Mon, Sep 07, 2009 at 10:44:07AM +0530, M. Mohan Kumar wrote:
> Write to HVC terminal from purgatory code
> 
> Current x86/x86-64 kexec-tools print the message "I'm in purgatory" to
> serial console/VGA while executing the purgatory code.  Implement this
> feature for POWERPC pseries platform by using the H_PUT_TERM_CHAR
> hypervisor call by printng to hvc console.

This change seems reasonable to me, can any of the ppc people offer a review?

> Signed-off-by: M. Mohan Kumar <mohan@in.ibm.com>
> ---
>  kexec/arch/ppc64/fs2dt.c               |   47 +++++++++++++++++++++++++++++++-
>  kexec/arch/ppc64/kexec-elf-ppc64.c     |    7 +++++
>  kexec/arch/ppc64/kexec-ppc64.h         |    1 +
>  purgatory/arch/ppc64/Makefile          |    1 +
>  purgatory/arch/ppc64/console-ppc64.c   |   14 +++++++++
>  purgatory/arch/ppc64/hvCall.S          |   28 +++++++++++++++++++
>  purgatory/arch/ppc64/hvCall.h          |    8 +++++
>  purgatory/arch/ppc64/purgatory-ppc64.c |    1 +
>  8 files changed, 106 insertions(+), 1 deletions(-)
>  create mode 100644 purgatory/arch/ppc64/hvCall.S
>  create mode 100644 purgatory/arch/ppc64/hvCall.h
> 
> diff --git a/kexec/arch/ppc64/fs2dt.c b/kexec/arch/ppc64/fs2dt.c
> index b01ff86..bd9d36c 100644
> --- a/kexec/arch/ppc64/fs2dt.c
> +++ b/kexec/arch/ppc64/fs2dt.c
> @@ -434,6 +434,9 @@ static void putnode(void)
>  	if (!strcmp(basename,"/chosen/")) {
>  		size_t cmd_len = 0;
>  		char *param = NULL;
> +		char filename[MAXPATH];
> +		char buff[64];

                Is always 64 big enough?
		It seems a bit arbitrary.

> +		int fd;
>  
>  		cmd_len = strlen(local_cmdline);
>  		if (cmd_len != 0) {
> @@ -446,7 +449,6 @@ static void putnode(void)
>  
>  		/* ... if not, grab root= from the old command line */
>  		if (!param) {
> -			char filename[MAXPATH];
>  			FILE *fp;
>  			char *last_cmdline = NULL;
>  			char *old_param;
> @@ -483,8 +485,51 @@ static void putnode(void)
>  		dt += (cmd_len + 3)/4;
>  
>  		fprintf(stderr, "Modified cmdline:%s\n", local_cmdline);
> +
> +		/*
> +		 * Determine the platform type/stdout type, so that purgatory
> +		 * code can print 'I'm in purgatory' message. Currently only
> +		 * pseries/hvcterminal is supported.
> +		 */
> +		strcpy(filename, pathname);
> +		strcat(filename, "linux,stdout-path");
> +		fd = open(filename, O_RDONLY);
> +		if (fd == -1) {
> +			printf("Unable to find linux,stdout-path, printing"
> +					" from purgatory is diabled\n");
> +			goto no_debug;
> +		}
> +		if (fstat(fd, &statbuf)) {
> +			printf("Unable to stat linux,stdout-path, printing"
> +					" from purgatory is diabled\n");
> +			close(fd);
> +			goto no_debug;
> +		}
> +		read(fd, buff, statbuf.st_size);
> +		close(fd);
> +		strcpy(filename, "/proc/device-tree/");
> +		strcat(filename, buff);
> +		strcat(filename, "/compatible");
> +		fd = open(filename, O_RDONLY);
> +		if (fd == -1) {
> +			printf("Unable to find linux,stdout-path/compatible, "
> +				" printing from purgatory is diabled\n");
> +			goto no_debug;
> +		}
> +		if (fstat(fd, &statbuf)) {
> +			printf("Unable to stat linux,stdout-path/compatible, "
> +				" printing from purgatory is diabled\n");
> +			close(fd);
> +			goto no_debug;
> +		}
> +		read(fd, buff, statbuf.st_size);
> +		if (!strcmp(buff, "hvterm1") ||
> +					!strcmp(buff, "hvterm-protocol"))
> +			my_debug = 1;
> +		close(fd);
>  	}
>  
> +no_debug:
>  	for (i=0; i < numlist; i++) {
>  		dp = namelist[i];
>  		strcpy(dn, dp->d_name);
> diff --git a/kexec/arch/ppc64/kexec-elf-ppc64.c b/kexec/arch/ppc64/kexec-elf-ppc64.c
> index 21533cb..65fc42f 100644
> --- a/kexec/arch/ppc64/kexec-elf-ppc64.c
> +++ b/kexec/arch/ppc64/kexec-elf-ppc64.c
> @@ -41,6 +41,8 @@
>  uint64_t initrd_base, initrd_size;
>  unsigned char reuse_initrd = 0;
>  const char *ramdisk;
> +/* Used for enabling printing message from purgatory code */
> +int my_debug = 0;
>  
>  int elf_ppc64_probe(const char *buf, off_t len)
>  {
> @@ -296,6 +298,8 @@ int elf_ppc64_load(int argc, char **argv, const char *buf, off_t len,
>  	toc_addr = my_r2(&info->rhdr);
>  	elf_rel_set_symbol(&info->rhdr, "my_toc", &toc_addr, sizeof(toc_addr));
>  
> +	/* Set debug */
> +	elf_rel_set_symbol(&info->rhdr, "debug", &my_debug, sizeof(my_debug));
>  #ifdef DEBUG
>  	my_kernel = 0;
>  	my_dt_offset = 0;
> @@ -304,6 +308,7 @@ int elf_ppc64_load(int argc, char **argv, const char *buf, off_t len,
>  	my_stack = 0;
>  	toc_addr = 0;
>  	my_run_at_load = 0;
> +	my_debug = 0;
>  
>  	elf_rel_get_symbol(&info->rhdr, "kernel", &my_kernel, sizeof(my_kernel));
>  	elf_rel_get_symbol(&info->rhdr, "dt_offset", &my_dt_offset,
> @@ -317,6 +322,7 @@ int elf_ppc64_load(int argc, char **argv, const char *buf, off_t len,
>  	elf_rel_get_symbol(&info->rhdr, "stack", &my_stack, sizeof(my_stack));
>  	elf_rel_get_symbol(&info->rhdr, "my_toc", &toc_addr,
>  				sizeof(toc_addr));
> +	elf_rel_get_symbol(&info->rhdr, "debug", &my_debug, sizeof(my_debug));
>  
>  	fprintf(stderr, "info->entry is %p\n", info->entry);
>  	fprintf(stderr, "kernel is %llx\n", (unsigned long long)my_kernel);
> @@ -329,6 +335,7 @@ int elf_ppc64_load(int argc, char **argv, const char *buf, off_t len,
>  	fprintf(stderr, "stack is %llx\n", (unsigned long long)my_stack);
>  	fprintf(stderr, "toc_addr is %llx\n", (unsigned long long)toc_addr);
>  	fprintf(stderr, "purgatory size is %zu\n", purgatory_size);
> +	fprintf(stderr, "debug is %d\n", my_debug);
>  #endif
>  
>  	for (i = 0; i < info->nr_segments; i++)
> diff --git a/kexec/arch/ppc64/kexec-ppc64.h b/kexec/arch/ppc64/kexec-ppc64.h
> index 920ac46..838c6da 100644
> --- a/kexec/arch/ppc64/kexec-ppc64.h
> +++ b/kexec/arch/ppc64/kexec-ppc64.h
> @@ -20,6 +20,7 @@ unsigned long my_r2(const struct mem_ehdr *ehdr);
>  extern uint64_t initrd_base, initrd_size;
>  extern int max_memory_ranges;
>  extern unsigned char reuse_initrd;
> +extern int my_debug;
>  
>  /* boot block version 2 as defined by the linux kernel */
>  struct bootblock {
> diff --git a/purgatory/arch/ppc64/Makefile b/purgatory/arch/ppc64/Makefile
> index aaa4046..40a9e99 100644
> --- a/purgatory/arch/ppc64/Makefile
> +++ b/purgatory/arch/ppc64/Makefile
> @@ -3,6 +3,7 @@
>  #
>  
>  ppc64_PURGATORY_SRCS += purgatory/arch/ppc64/v2wrap.S
> +ppc64_PURGATORY_SRCS += purgatory/arch/ppc64/hvCall.S
>  ppc64_PURGATORY_SRCS += purgatory/arch/ppc64/purgatory-ppc64.c
>  ppc64_PURGATORY_SRCS += purgatory/arch/ppc64/console-ppc64.c
>  ppc64_PURGATORY_SRCS += purgatory/arch/ppc64/crashdump_backup.c
> diff --git a/purgatory/arch/ppc64/console-ppc64.c b/purgatory/arch/ppc64/console-ppc64.c
> index d6da7b3..78a233b 100644
> --- a/purgatory/arch/ppc64/console-ppc64.c
> +++ b/purgatory/arch/ppc64/console-ppc64.c
> @@ -20,8 +20,22 @@
>   */
>  
>  #include <purgatory.h>
> +#include "hvCall.h"
> +
> +extern int debug;
>  
>  void putchar(int c)
>  {
> +	char buff[16];
> +	unsigned long *lbuf = (unsigned long *)buff;
> +
> +	if (!debug) /* running on non pseries */
> +		return;
> +
> +	if (c == '\n')
> +		putchar('\r');
> +
> +	buff[0] = c;
> +	plpar_hcall_norets(H_PUT_TERM_CHAR, 0, 1, lbuf[0], lbuf[1]);
>  	return;
>  }
> diff --git a/purgatory/arch/ppc64/hvCall.S b/purgatory/arch/ppc64/hvCall.S
> new file mode 100644
> index 0000000..e401f81
> --- /dev/null
> +++ b/purgatory/arch/ppc64/hvCall.S
> @@ -0,0 +1,28 @@
> +/*
> + * This file contains the generic function to perform a call to the
> + * pSeries LPAR hypervisor.
> + *
> + * Created by M. Mohan Kumar (mohan@in.ibm.com)
> + * Copyright (C) IBM Corporation
> + * Taken from linux/arch/powerpc/platforms/pseries/hvCall.S
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License
> + * as published by the Free Software Foundation; either version
> + * 2 of the License, or (at your option) any later version.
> + */
> +
> +#define HVSC	.long 0x44000022
> +.text
> +	.machine ppc64
> +.globl .plpar_hcall_norets
> +.plpar_hcall_norets:
> +	or	6,6,6			# medium low priority
> +        mfcr	0
> +        stw	0,8(1)
> +
> +        HVSC 				/* invoke the hypervisor */
> +
> +        lwz	0,8(1)
> +        mtcrf	0xff,0
> +        blr                             /* return r3 = status */
> diff --git a/purgatory/arch/ppc64/hvCall.h b/purgatory/arch/ppc64/hvCall.h
> new file mode 100644
> index 0000000..187e24d
> --- /dev/null
> +++ b/purgatory/arch/ppc64/hvCall.h
> @@ -0,0 +1,8 @@
> +#ifndef HVCALL_H
> +#define HVCALL_H
> +
> +#define H_PUT_TERM_CHAR	0x58
> +
> +long plpar_hcall_norets(unsigned long opcode, ...);
> +
> +#endif
> diff --git a/purgatory/arch/ppc64/purgatory-ppc64.c b/purgatory/arch/ppc64/purgatory-ppc64.c
> index 93f28d2..0b6d326 100644
> --- a/purgatory/arch/ppc64/purgatory-ppc64.c
> +++ b/purgatory/arch/ppc64/purgatory-ppc64.c
> @@ -28,6 +28,7 @@ unsigned long stack = 0;
>  unsigned long dt_offset = 0;
>  unsigned long my_toc = 0;
>  unsigned long kernel = 0;
> +unsigned int debug = 0;
>  
>  void setup_arch(void)
>  {
> -- 
> 1.6.2.5

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [RFC] [PATCH] Write to HVC terminal from purgatory code
  2009-09-08 23:09   ` Simon Horman
@ 2009-09-17  9:06     ` M. Mohan Kumar
  -1 siblings, 0 replies; 8+ messages in thread
From: M. Mohan Kumar @ 2009-09-17  9:06 UTC (permalink / raw)
  To: kexec; +Cc: linuxppc-dev, Simon Horman, miltonm

> On Mon, Sep 07, 2009 at 10:44:07AM +0530, M. Mohan Kumar wrote:
> > Write to HVC terminal from purgatory code
> >
> > Current x86/x86-64 kexec-tools print the message "I'm in purgatory" to
> > serial console/VGA while executing the purgatory code.  Implement this
> > feature for POWERPC pseries platform by using the H_PUT_TERM_CHAR
> > hypervisor call by printng to hvc console.
>
> This change seems reasonable to me, can any of the ppc people offer a
> review?
>

Sorry, I forgot to mention that this patch is tested on POWER5 (under 
hypervisor) and POWER4 Full System partition mode (under non-hypervisor)

Regards,
M. Mohan Kumar.

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [RFC] [PATCH] Write to HVC terminal from purgatory code
@ 2009-09-17  9:06     ` M. Mohan Kumar
  0 siblings, 0 replies; 8+ messages in thread
From: M. Mohan Kumar @ 2009-09-17  9:06 UTC (permalink / raw)
  To: kexec; +Cc: linuxppc-dev, Simon Horman, miltonm

> On Mon, Sep 07, 2009 at 10:44:07AM +0530, M. Mohan Kumar wrote:
> > Write to HVC terminal from purgatory code
> >
> > Current x86/x86-64 kexec-tools print the message "I'm in purgatory" to
> > serial console/VGA while executing the purgatory code.  Implement this
> > feature for POWERPC pseries platform by using the H_PUT_TERM_CHAR
> > hypervisor call by printng to hvc console.
>
> This change seems reasonable to me, can any of the ppc people offer a
> review?
>

Sorry, I forgot to mention that this patch is tested on POWER5 (under 
hypervisor) and POWER4 Full System partition mode (under non-hypervisor)

Regards,
M. Mohan Kumar.

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [RFC] [PATCH] Write to HVC terminal from purgatory code
  2009-09-07  5:14 ` M. Mohan Kumar
@ 2009-09-17 11:54   ` Michael Ellerman
  -1 siblings, 0 replies; 8+ messages in thread
From: Michael Ellerman @ 2009-09-17 11:54 UTC (permalink / raw)
  To: mohan; +Cc: linuxppc-dev, horms, kexec, miltonm

[-- Attachment #1: Type: text/plain, Size: 4863 bytes --]

On Mon, 2009-09-07 at 10:44 +0530, M. Mohan Kumar wrote:
> Write to HVC terminal from purgatory code
> 
> Current x86/x86-64 kexec-tools print the message "I'm in purgatory" to
> serial console/VGA while executing the purgatory code.  Implement this
> feature for POWERPC pseries platform by using the H_PUT_TERM_CHAR
> hypervisor call by printng to hvc console.


Hi Mohan, just a few comments ...

> diff --git a/kexec/arch/ppc64/fs2dt.c b/kexec/arch/ppc64/fs2dt.c
> index b01ff86..bd9d36c 100644
> --- a/kexec/arch/ppc64/fs2dt.c
> +++ b/kexec/arch/ppc64/fs2dt.c
> @@ -434,6 +434,9 @@ static void putnode(void)
>  	if (!strcmp(basename,"/chosen/")) {
>  		size_t cmd_len = 0;
>  		char *param = NULL;
> +		char filename[MAXPATH];
> +		char buff[64];
> +		int fd;
>  
>  		cmd_len = strlen(local_cmdline);
>  		if (cmd_len != 0) {
> @@ -446,7 +449,6 @@ static void putnode(void)
>  
>  		/* ... if not, grab root= from the old command line */
>  		if (!param) {
> -			char filename[MAXPATH];
>  			FILE *fp;
>  			char *last_cmdline = NULL;
>  			char *old_param;
> @@ -483,8 +485,51 @@ static void putnode(void)
>  		dt += (cmd_len + 3)/4;
>  
>  		fprintf(stderr, "Modified cmdline:%s\n", local_cmdline);
> +
> +		/*
> +		 * Determine the platform type/stdout type, so that purgatory
> +		 * code can print 'I'm in purgatory' message. Currently only
> +		 * pseries/hvcterminal is supported.
> +		 */
> +		strcpy(filename, pathname);
> +		strcat(filename, "linux,stdout-path");

strncat() ?

> +		fd = open(filename, O_RDONLY);
> +		if (fd == -1) {
> +			printf("Unable to find linux,stdout-path, printing"
> +					" from purgatory is diabled\n");
> +			goto no_debug;
> +		}
> +		if (fstat(fd, &statbuf)) {
> +			printf("Unable to stat linux,stdout-path, printing"
> +					" from purgatory is diabled\n");
> +			close(fd);
> +			goto no_debug;
> +		}
> +		read(fd, buff, statbuf.st_size);

Be nice to check it's going to fit in buff here.

> +		close(fd);
> +		strcpy(filename, "/proc/device-tree/");
> +		strcat(filename, buff);
> +		strcat(filename, "/compatible");

strncpy / strncat.

> +		fd = open(filename, O_RDONLY);
> +		if (fd == -1) {
> +			printf("Unable to find linux,stdout-path/compatible, "
> +				" printing from purgatory is diabled\n");

You may as well print the actual path here, seeing as you have it.

> +			goto no_debug;
> +		}
> +		if (fstat(fd, &statbuf)) {
> +			printf("Unable to stat linux,stdout-path/compatible, "
> +				" printing from purgatory is diabled\n");
> +			close(fd);
> +			goto no_debug;
> +		}
> +		read(fd, buff, statbuf.st_size);
> +		if (!strcmp(buff, "hvterm1") ||
> +					!strcmp(buff, "hvterm-protocol"))
> +			my_debug = 1;

I have a personal hatred for variables called my_foo, but that's just
personal taste I guess :)

> +		close(fd);
>  	}
>  
> +no_debug:
>  	for (i=0; i < numlist; i++) {
>  		dp = namelist[i];
>  		strcpy(dn, dp->d_name);

> diff --git a/purgatory/arch/ppc64/console-ppc64.c b/purgatory/arch/ppc64/console-ppc64.c
> index d6da7b3..78a233b 100644
> --- a/purgatory/arch/ppc64/console-ppc64.c
> +++ b/purgatory/arch/ppc64/console-ppc64.c
> @@ -20,8 +20,22 @@
>   */
>  
>  #include <purgatory.h>
> +#include "hvCall.h"
> +
> +extern int debug;
>  
>  void putchar(int c)
>  {
> +	char buff[16];
> +	unsigned long *lbuf = (unsigned long *)buff;
> +
> +	if (!debug) /* running on non pseries */
> +		return;
> +
> +	if (c == '\n')
> +		putchar('\r');
> +
> +	buff[0] = c;
> +	plpar_hcall_norets(H_PUT_TERM_CHAR, 0, 1, lbuf[0], lbuf[1]);
>  	return;
>  }
> diff --git a/purgatory/arch/ppc64/hvCall.S b/purgatory/arch/ppc64/hvCall.S
> new file mode 100644
> index 0000000..e401f81
> --- /dev/null
> +++ b/purgatory/arch/ppc64/hvCall.S
> @@ -0,0 +1,28 @@
> +/*
> + * This file contains the generic function to perform a call to the
> + * pSeries LPAR hypervisor.
> + *
> + * Created by M. Mohan Kumar (mohan@in.ibm.com)
> + * Copyright (C) IBM Corporation
> + * Taken from linux/arch/powerpc/platforms/pseries/hvCall.S
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License
> + * as published by the Free Software Foundation; either version
> + * 2 of the License, or (at your option) any later version.
> + */
> +
> +#define HVSC	.long 0x44000022
> +.text
> +	.machine ppc64
> +.globl .plpar_hcall_norets
> +.plpar_hcall_norets:
> +	or	6,6,6			# medium low priority
> +        mfcr	0
> +        stw	0,8(1)
> +
> +        HVSC 				/* invoke the hypervisor */
> +
> +        lwz	0,8(1)
> +        mtcrf	0xff,0
> +        blr                             /* return r3 = status */

It's much easier to read if you use r0, r1 etc.


cheers

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 197 bytes --]

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [RFC] [PATCH] Write to HVC terminal from purgatory code
@ 2009-09-17 11:54   ` Michael Ellerman
  0 siblings, 0 replies; 8+ messages in thread
From: Michael Ellerman @ 2009-09-17 11:54 UTC (permalink / raw)
  To: mohan; +Cc: linuxppc-dev, horms, kexec, miltonm


[-- Attachment #1.1: Type: text/plain, Size: 4863 bytes --]

On Mon, 2009-09-07 at 10:44 +0530, M. Mohan Kumar wrote:
> Write to HVC terminal from purgatory code
> 
> Current x86/x86-64 kexec-tools print the message "I'm in purgatory" to
> serial console/VGA while executing the purgatory code.  Implement this
> feature for POWERPC pseries platform by using the H_PUT_TERM_CHAR
> hypervisor call by printng to hvc console.


Hi Mohan, just a few comments ...

> diff --git a/kexec/arch/ppc64/fs2dt.c b/kexec/arch/ppc64/fs2dt.c
> index b01ff86..bd9d36c 100644
> --- a/kexec/arch/ppc64/fs2dt.c
> +++ b/kexec/arch/ppc64/fs2dt.c
> @@ -434,6 +434,9 @@ static void putnode(void)
>  	if (!strcmp(basename,"/chosen/")) {
>  		size_t cmd_len = 0;
>  		char *param = NULL;
> +		char filename[MAXPATH];
> +		char buff[64];
> +		int fd;
>  
>  		cmd_len = strlen(local_cmdline);
>  		if (cmd_len != 0) {
> @@ -446,7 +449,6 @@ static void putnode(void)
>  
>  		/* ... if not, grab root= from the old command line */
>  		if (!param) {
> -			char filename[MAXPATH];
>  			FILE *fp;
>  			char *last_cmdline = NULL;
>  			char *old_param;
> @@ -483,8 +485,51 @@ static void putnode(void)
>  		dt += (cmd_len + 3)/4;
>  
>  		fprintf(stderr, "Modified cmdline:%s\n", local_cmdline);
> +
> +		/*
> +		 * Determine the platform type/stdout type, so that purgatory
> +		 * code can print 'I'm in purgatory' message. Currently only
> +		 * pseries/hvcterminal is supported.
> +		 */
> +		strcpy(filename, pathname);
> +		strcat(filename, "linux,stdout-path");

strncat() ?

> +		fd = open(filename, O_RDONLY);
> +		if (fd == -1) {
> +			printf("Unable to find linux,stdout-path, printing"
> +					" from purgatory is diabled\n");
> +			goto no_debug;
> +		}
> +		if (fstat(fd, &statbuf)) {
> +			printf("Unable to stat linux,stdout-path, printing"
> +					" from purgatory is diabled\n");
> +			close(fd);
> +			goto no_debug;
> +		}
> +		read(fd, buff, statbuf.st_size);

Be nice to check it's going to fit in buff here.

> +		close(fd);
> +		strcpy(filename, "/proc/device-tree/");
> +		strcat(filename, buff);
> +		strcat(filename, "/compatible");

strncpy / strncat.

> +		fd = open(filename, O_RDONLY);
> +		if (fd == -1) {
> +			printf("Unable to find linux,stdout-path/compatible, "
> +				" printing from purgatory is diabled\n");

You may as well print the actual path here, seeing as you have it.

> +			goto no_debug;
> +		}
> +		if (fstat(fd, &statbuf)) {
> +			printf("Unable to stat linux,stdout-path/compatible, "
> +				" printing from purgatory is diabled\n");
> +			close(fd);
> +			goto no_debug;
> +		}
> +		read(fd, buff, statbuf.st_size);
> +		if (!strcmp(buff, "hvterm1") ||
> +					!strcmp(buff, "hvterm-protocol"))
> +			my_debug = 1;

I have a personal hatred for variables called my_foo, but that's just
personal taste I guess :)

> +		close(fd);
>  	}
>  
> +no_debug:
>  	for (i=0; i < numlist; i++) {
>  		dp = namelist[i];
>  		strcpy(dn, dp->d_name);

> diff --git a/purgatory/arch/ppc64/console-ppc64.c b/purgatory/arch/ppc64/console-ppc64.c
> index d6da7b3..78a233b 100644
> --- a/purgatory/arch/ppc64/console-ppc64.c
> +++ b/purgatory/arch/ppc64/console-ppc64.c
> @@ -20,8 +20,22 @@
>   */
>  
>  #include <purgatory.h>
> +#include "hvCall.h"
> +
> +extern int debug;
>  
>  void putchar(int c)
>  {
> +	char buff[16];
> +	unsigned long *lbuf = (unsigned long *)buff;
> +
> +	if (!debug) /* running on non pseries */
> +		return;
> +
> +	if (c == '\n')
> +		putchar('\r');
> +
> +	buff[0] = c;
> +	plpar_hcall_norets(H_PUT_TERM_CHAR, 0, 1, lbuf[0], lbuf[1]);
>  	return;
>  }
> diff --git a/purgatory/arch/ppc64/hvCall.S b/purgatory/arch/ppc64/hvCall.S
> new file mode 100644
> index 0000000..e401f81
> --- /dev/null
> +++ b/purgatory/arch/ppc64/hvCall.S
> @@ -0,0 +1,28 @@
> +/*
> + * This file contains the generic function to perform a call to the
> + * pSeries LPAR hypervisor.
> + *
> + * Created by M. Mohan Kumar (mohan@in.ibm.com)
> + * Copyright (C) IBM Corporation
> + * Taken from linux/arch/powerpc/platforms/pseries/hvCall.S
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License
> + * as published by the Free Software Foundation; either version
> + * 2 of the License, or (at your option) any later version.
> + */
> +
> +#define HVSC	.long 0x44000022
> +.text
> +	.machine ppc64
> +.globl .plpar_hcall_norets
> +.plpar_hcall_norets:
> +	or	6,6,6			# medium low priority
> +        mfcr	0
> +        stw	0,8(1)
> +
> +        HVSC 				/* invoke the hypervisor */
> +
> +        lwz	0,8(1)
> +        mtcrf	0xff,0
> +        blr                             /* return r3 = status */

It's much easier to read if you use r0, r1 etc.


cheers

[-- Attachment #1.2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 197 bytes --]

[-- Attachment #2: Type: text/plain, Size: 143 bytes --]

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2009-09-17 11:54 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-09-07  5:14 [RFC] [PATCH] Write to HVC terminal from purgatory code M. Mohan Kumar
2009-09-07  5:14 ` M. Mohan Kumar
2009-09-08 23:09 ` Simon Horman
2009-09-08 23:09   ` Simon Horman
2009-09-17  9:06   ` M. Mohan Kumar
2009-09-17  9:06     ` M. Mohan Kumar
2009-09-17 11:54 ` Michael Ellerman
2009-09-17 11:54   ` Michael Ellerman

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.