mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	The paca display is already more than 24 lines, which can be problematic if you have an old school 80x24 terminal, or more likely you are on a virtual terminal which does not scroll for whatever reason. This patch adds a new command "#", which takes a single (hex) numeric argument: lines per page. It will cause the output of "dp" and "dpa" to be broken into pages, if necessary. Sample output: 0:mon> # 10 0:mon> dp1 paca for cpu 0x1 @ c00000000fdc0480: possible = yes present = yes online = yes lock_token = 0x8000 (0x8) paca_index = 0x1 (0xa) kernel_toc = 0xc000000000eb2400 (0x10) kernelbase = 0xc000000000000000 (0x18) kernel_msr = 0xb000000000001032 (0x20) emergency_sp = 0xc00000003ffe8000 (0x28) mc_emergency_sp = 0xc00000003ffe4000 (0x2e0) in_mce = 0x0 (0x2e8) data_offset = 0x7f170000 (0x30) hw_cpu_id = 0x8 (0x38) cpu_start = 0x1 (0x3a) kexec_state = 0x0 (0x3b) [Hit a key (a:all, q:truncate, any:next page)] 0:mon> __current = 0xc00000007e696620 (0x290) kstack = 0xc00000007e6ebe30 (0x298) stab_rr = 0xb (0x2a0) saved_r1 = 0xc00000007ef37860 (0x2a8) trap_save = 0x0 (0x2b8) soft_enabled = 0x0 (0x2ba) irq_happened = 0x1 (0x2bb) io_sync = 0x0 (0x2bc) irq_work_pending = 0x0 (0x2bd) nap_state_lost = 0x0 (0x2be) 0:mon> Signed-off-by: Sam Bobroff <sam.bobroff@au1.ibm.com> [mpe: Use bool, make some variables static] Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
		
			
				
	
	
		
			192 lines
		
	
	
	
		
			3.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			192 lines
		
	
	
	
		
			3.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*
 | 
						|
 * Copyright (C) 1996-2005 Paul Mackerras.
 | 
						|
 *
 | 
						|
 *      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.
 | 
						|
 */
 | 
						|
#include <linux/string.h>
 | 
						|
#include <asm/udbg.h>
 | 
						|
#include <asm/time.h>
 | 
						|
#include "nonstdio.h"
 | 
						|
 | 
						|
static bool paginating, paginate_skipping;
 | 
						|
static unsigned long paginate_lpp; /* Lines Per Page */
 | 
						|
static unsigned long paginate_pos;
 | 
						|
 | 
						|
void xmon_start_pagination(void)
 | 
						|
{
 | 
						|
	paginating = true;
 | 
						|
	paginate_skipping = false;
 | 
						|
	paginate_pos = 0;
 | 
						|
}
 | 
						|
 | 
						|
void xmon_end_pagination(void)
 | 
						|
{
 | 
						|
	paginating = false;
 | 
						|
}
 | 
						|
 | 
						|
void xmon_set_pagination_lpp(unsigned long lpp)
 | 
						|
{
 | 
						|
	paginate_lpp = lpp;
 | 
						|
}
 | 
						|
 | 
						|
static int xmon_readchar(void)
 | 
						|
{
 | 
						|
	if (udbg_getc)
 | 
						|
		return udbg_getc();
 | 
						|
	return -1;
 | 
						|
}
 | 
						|
 | 
						|
static int xmon_write(const char *ptr, int nb)
 | 
						|
{
 | 
						|
	int rv = 0;
 | 
						|
	const char *p = ptr, *q;
 | 
						|
	const char msg[] = "[Hit a key (a:all, q:truncate, any:next page)]";
 | 
						|
 | 
						|
	if (nb <= 0)
 | 
						|
		return rv;
 | 
						|
 | 
						|
	if (paginating && paginate_skipping)
 | 
						|
		return nb;
 | 
						|
 | 
						|
	if (paginate_lpp) {
 | 
						|
		while (paginating && (q = strchr(p, '\n'))) {
 | 
						|
			rv += udbg_write(p, q - p + 1);
 | 
						|
			p = q + 1;
 | 
						|
			paginate_pos++;
 | 
						|
 | 
						|
			if (paginate_pos >= paginate_lpp) {
 | 
						|
				udbg_write(msg, strlen(msg));
 | 
						|
 | 
						|
				switch (xmon_readchar()) {
 | 
						|
				case 'a':
 | 
						|
					paginating = false;
 | 
						|
					break;
 | 
						|
				case 'q':
 | 
						|
					paginate_skipping = true;
 | 
						|
					break;
 | 
						|
				default:
 | 
						|
					/* nothing */
 | 
						|
					break;
 | 
						|
				}
 | 
						|
 | 
						|
				paginate_pos = 0;
 | 
						|
				udbg_write("\r\n", 2);
 | 
						|
 | 
						|
				if (paginate_skipping)
 | 
						|
					return nb;
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	return rv + udbg_write(p, nb - (p - ptr));
 | 
						|
}
 | 
						|
 | 
						|
int xmon_putchar(int c)
 | 
						|
{
 | 
						|
	char ch = c;
 | 
						|
 | 
						|
	if (c == '\n')
 | 
						|
		xmon_putchar('\r');
 | 
						|
	return xmon_write(&ch, 1) == 1? c: -1;
 | 
						|
}
 | 
						|
 | 
						|
static char line[256];
 | 
						|
static char *lineptr;
 | 
						|
static int lineleft;
 | 
						|
 | 
						|
static int xmon_getchar(void)
 | 
						|
{
 | 
						|
	int c;
 | 
						|
 | 
						|
	if (lineleft == 0) {
 | 
						|
		lineptr = line;
 | 
						|
		for (;;) {
 | 
						|
			c = xmon_readchar();
 | 
						|
			if (c == -1 || c == 4)
 | 
						|
				break;
 | 
						|
			if (c == '\r' || c == '\n') {
 | 
						|
				*lineptr++ = '\n';
 | 
						|
				xmon_putchar('\n');
 | 
						|
				break;
 | 
						|
			}
 | 
						|
			switch (c) {
 | 
						|
			case 0177:
 | 
						|
			case '\b':
 | 
						|
				if (lineptr > line) {
 | 
						|
					xmon_putchar('\b');
 | 
						|
					xmon_putchar(' ');
 | 
						|
					xmon_putchar('\b');
 | 
						|
					--lineptr;
 | 
						|
				}
 | 
						|
				break;
 | 
						|
			case 'U' & 0x1F:
 | 
						|
				while (lineptr > line) {
 | 
						|
					xmon_putchar('\b');
 | 
						|
					xmon_putchar(' ');
 | 
						|
					xmon_putchar('\b');
 | 
						|
					--lineptr;
 | 
						|
				}
 | 
						|
				break;
 | 
						|
			default:
 | 
						|
				if (lineptr >= &line[sizeof(line) - 1])
 | 
						|
					xmon_putchar('\a');
 | 
						|
				else {
 | 
						|
					xmon_putchar(c);
 | 
						|
					*lineptr++ = c;
 | 
						|
				}
 | 
						|
			}
 | 
						|
		}
 | 
						|
		lineleft = lineptr - line;
 | 
						|
		lineptr = line;
 | 
						|
	}
 | 
						|
	if (lineleft == 0)
 | 
						|
		return -1;
 | 
						|
	--lineleft;
 | 
						|
	return *lineptr++;
 | 
						|
}
 | 
						|
 | 
						|
char *xmon_gets(char *str, int nb)
 | 
						|
{
 | 
						|
	char *p;
 | 
						|
	int c;
 | 
						|
 | 
						|
	for (p = str; p < str + nb - 1; ) {
 | 
						|
		c = xmon_getchar();
 | 
						|
		if (c == -1) {
 | 
						|
			if (p == str)
 | 
						|
				return NULL;
 | 
						|
			break;
 | 
						|
		}
 | 
						|
		*p++ = c;
 | 
						|
		if (c == '\n')
 | 
						|
			break;
 | 
						|
	}
 | 
						|
	*p = 0;
 | 
						|
	return str;
 | 
						|
}
 | 
						|
 | 
						|
void xmon_printf(const char *format, ...)
 | 
						|
{
 | 
						|
	va_list args;
 | 
						|
	static char xmon_outbuf[1024];
 | 
						|
	int rc, n;
 | 
						|
 | 
						|
	va_start(args, format);
 | 
						|
	n = vsnprintf(xmon_outbuf, sizeof(xmon_outbuf), format, args);
 | 
						|
	va_end(args);
 | 
						|
 | 
						|
	rc = xmon_write(xmon_outbuf, n);
 | 
						|
 | 
						|
	if (n && rc == 0) {
 | 
						|
		/* No udbg hooks, fallback to printk() - dangerous */
 | 
						|
		printk("%s", xmon_outbuf);
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
void xmon_puts(const char *str)
 | 
						|
{
 | 
						|
	xmon_write(str, strlen(str));
 | 
						|
}
 |