[Pdbg] [PATCH] pdbg: implement 'log' command

Alistair Popple alistair at popple.id.au
Mon May 21 11:54:04 AEST 2018


On Friday, 18 May 2018 4:57:28 PM AEST Joel Stanley wrote:
> This command fetches the skiboot in-memory log from host RAM and
> display it on stdout.
> 
> Signed-off-by: Joel Stanley <joel at jms.id.au>
> ---
> Based on top of Balbir's logging patches.

I assume you mean Amitay's? ;)

> +ssize_t adu_read_from_buffer(struct pdbg_target *target, void *to, size_t count,
> +			     loff_t *ppos, uint64_t from, size_t available)

Bit of a nit pick but why do you use host sized variable types here (eg.
loff_t)? Technically these are the same regardless of host (ie. BMC)
architecture as they are defined by the debug target architecture (ie. PPC64).

Really we should define some debug target specific types for this (eg.
target_real_addr_t) but so far we haven't bothered to.

- Alistair

> +{
> +	loff_t pos = *ppos;
> +	int rc;
> +
> +	if (pos < 0)
> +		return -EINVAL;
> +	if (pos >= available)
> +		return 0;
> +	if (count > available - pos)
> +		count = available - pos;
> +
> +	pdbg_set_progress_tick(progress_tick);
> +	progress_init();
> +	rc = adu_getmem(target, from + pos, to, count);
> +	if (rc < 0) {
> +		PR_ERROR("unable to read memory");
> +		return rc;
> +	}
> +	progress_end();
> +
> +	*ppos = pos + count;
> +
> +	return count;
> +}
> +
> +ssize_t msglog_copy(struct pdbg_target *target, uint64_t memcons_addr,
> +		    char *to, loff_t pos, size_t count)
> +{
> +	struct memcons mc;
> +	uint64_t conbuf;
> +	ssize_t ret;
> +	size_t first_read = 0;
> +	uint32_t out_pos, avail;
> +
> +	ret = adu_getmem(target, memcons_addr, (uint8_t *)&mc, sizeof(mc));
> +	if (ret < 0) {
> +		PR_ERROR("unable to read memory\n");
> +		return -1;
> +	}
> +
> +	if (be64toh(mc.magic) != MEMCONS_MAGIC) {
> +                PR_ERROR("memory console version is invalid: %016"PRIx64"\n", be64toh(mc.magic));
> +                return -1;
> +        }
> +
> +	out_pos = be32toh(mc.out_pos);
> +	conbuf = be64toh(mc.obuf_phys);
> +
> +	/* When the buffer has wrapped, read from the out_pos marker to the end
> +	 * of the buffer, and then read the remaining data as in the un-wrapped
> +	 * case. */
> +	if (out_pos & MEMCONS_OUT_POS_WRAP) {
> +
> +		out_pos &= MEMCONS_OUT_POS_MASK;
> +		avail = be64toh(mc.obuf_size) - out_pos;
> +
> +		ret = adu_read_from_buffer(target, to, count, &pos,
> +				conbuf + out_pos, avail);
> +		if (ret < 0)
> +			goto out;
> +
> +		first_read = ret;
> +		to += first_read;
> +		count -= first_read;
> +		pos -= avail;
> +
> +		if (count <= 0)
> +			goto out;
> +	}
> +
> +	/* Sanity check. The firmware should not do this to us. */
> +	if (out_pos > be64toh(mc.obuf_size)) {
> +		PR_ERROR("memory console corruption. Aborting read.\n");
> +		return -EINVAL;
> +	}
> +
> +	ret = adu_read_from_buffer(target, to, count, &pos, conbuf, out_pos);
> +	if (ret < 0)
> +		goto out;
> +
> +	progress_end();
> +
> +	ret += first_read;
> +out:
> +	return ret;
> +}
> +
> +
> +int display_log(struct pdbg_target *target, uint64_t memcons, int skip_bytes)
> +{
> +	char *buf = calloc(INMEM_CON_LEN, 1);
> +	int ret;
> +
> +	ret = msglog_copy(target, memcons, buf, skip_bytes, INMEM_CON_LEN); 
> +	if (ret < 0)
> +		return ret;
> +
> +	printf("%s\n", buf);
> +	free(buf);
> +
> +	return 0;
> +}
> +
> +int handle_log(int optind, int argc, char *argv[])
> +{
> +	struct pdbg_target *target;
> +	struct debug_descriptor dd;
> +	uint64_t dd_addr;
> +	int skip_bytes = 24;
> +	int ret;
> +
> +	pdbg_for_each_class_target("adu", target) {
> +		if (!target_selected(target->parent))
> +			continue;
> +		if (pdbg_target_probe(target) != PDBG_TARGET_ENABLED)
> +			continue;
> +		break;
> +	};
> +	assert(target);
> +
> +	ret = adu_getmem(target, 0x30000080, (uint8_t *)&dd_addr, sizeof(dd_addr));
> +	if (ret < 0) {
> +		PR_ERROR("unable to read memory\n");
> +		return ret;
> +	}
> +	dd_addr = be64toh(dd_addr);
> +
> +	ret = adu_getmem(target, dd_addr, (uint8_t *)&dd, sizeof(dd));
> +	if (ret < 0) {
> +		PR_ERROR("unable to read memory\n");
> +		return ret;
> +	}
> +
> +	ret = display_log(target, be64toh(dd.memcons_phys), skip_bytes);
> +	if (ret < 0) {
> +		PR_ERROR("unable to display log\n");
> +		return ret;
> +	}
> +	return 0;
> +}
> diff --git a/src/main.c b/src/main.c
> index 82a20c9dd3fc..14c038ef730f 100644
> --- a/src/main.c
> +++ b/src/main.c
> @@ -31,6 +31,7 @@
>  #include <config.h>
>  
>  #include <libpdbg.h>
> +#include <debug.h>
>  
>  #include "main.h"
>  #include "bitutils.h"
> @@ -41,6 +42,7 @@
>  #include "mem.h"
>  #include "thread.h"
>  #include "htm.h"
> +#include "log.h"
>  #include "options.h"
>  
>  #define THREADS_PER_CORE	8
> @@ -103,6 +105,7 @@ static struct action actions[] = {
>  	{ "threadstatus", "", "Print the status of a thread", &thread_status_print },
>  	{ "sreset",  "", "Reset", &thread_sreset },
>  	{ "regs",  "", "State", &thread_state },
> +	{ "log", "[-n <lines>]", "Display skiboot log", &handle_log },
>  };
>  
>  
> 




More information about the Pdbg mailing list