[PATCH v1 3/4] arm64: Add arm64 kexec support

Mark Rutland mark.rutland at arm.com
Thu Jul 21 03:31:21 PDT 2016


On Wed, Jul 20, 2016 at 12:19:21PM -0700, Geoff Levand wrote:
> > > +static uint64_t read_sink(const char *command_line)
> > > +{
> > > +> > 	> > uint64_t v;
> > > +> > 	> > const char *p;
> > > +
> > > +> > 	> > if (arm64_opts.port)
> > > +> > 	> > 	> > return arm64_opts.port;
> > > +
> > > +#if defined(ARM64_DEBUG_PORT)
> > > +> > 	> > return (uint64_t)(ARM64_DEBUG_PORT);
> > > +#endif
> > > +> > 	> > if (!command_line)
> > > +> > 	> > 	> > return 0;
> > > +
> > > +> > 	> > if (!(p = strstr(command_line, "earlyprintk=")) &&
> > > +> > 	> > 	> > !(p = strstr(command_line, "earlycon=")))
> > > +> > 	> > 	> > return 0;
> > > +
> > > +> > 	> > while (*p != ',')
> > > +> > 	> > 	> > p++;
> > > +
> > > +> > 	> > p++;
> > > +
> > > +> > 	> > while (isspace(*p))
> > > +> > 	> > 	> > p++;
> > 
> > Why do we skip spaces? As far as I am aware, there should not be any
> > spaces in the option.
> 
> Sure, I can remove it.
> 
> > > +
> > > +> > 	> > if (*p == 0)
> > > +> > 	> > 	> > return 0;
> > > +
> > > +> > 	> > errno = 0;
> > > +
> > > +> > 	> > v = strtoull(p, NULL, 0);
> > > +
> > > +> > 	> > if (errno)
> > > +> > 	> > 	> > return 0;
> > > +
> > > +> > 	> > return v;
> > > +}
> > 
> > It looks like the purgatory code expects angel SWI as the earlycon,
> 
> Maybe you saw the debug_brk macro in entry.S?  I should remove
> that and just loop.

Ah, sorry. For some reason I got that confused with the sink code. My
bad.

Now I see that's assuming an 8-bit MMIO register.

> > whereas many other earlycons exist (with pl011 being extremely popular).
> > Regardless, if we assume a particular UART type, we should explicitly
> > verify that here. Otherwise the purgatory code will likely bring down
> > the system, and it will be very painful to debug.
> > 
> > Please explicitly check for the supported earlycon name.
> 
> Purgatory just writes bytes to the address given.  Are there
> UARTs that don't have TX as the first port?

I'm not sure, but it's certainly possible. The generic earlycon binding
doesn't guarantee that the first address is a TX register. Even if they
don't exist today, they could in a month's time, so I don't think we
should assume anything.

Additionally, the width of that TX register can differ (e.g.
uart8250,mmio vs uart8250,mmio32), and some UARTs aren't very forgiving
if accessed with the wrong width.

> To be safe, we could do a check when we get the address from
> an earlycon parameter. 

Yup. I think you need a whitelist of UARTs that can be handled, along
with parsing for their options (e.g. mmio vs mmio32), giving up if
unknown options are spotted.

> Here's what I found in the dts'.  The
> first three are OK, but I don't know about the others.  

I believe you can find the full set with:

$ git grep EARLYCON_DECLARE

[...]

> > > +> > 	> > if (result)
> > > +> > 	> > 	> > fprintf(stderr, "kexec: Warning: No device tree available.\n");
> > 
> > There are other reasons we'd return an error (e.g. mismatched enable
> > methods), so this is somewhat misleading.
> > 
> > I believe that in all cases we log the specific reason first anyway, so
> > perhaps it's best to jsut remove this warning.
> 
> Yes, this could be removed.
> 
> > Won't this also be very noisy in the case of ACPI with a stub DTB? In
> > that case ther are no cpu nodes, and may be no memory nodes.
> 
> Should we just remove check_cpu_nodes and everything associated with
> it?  It is a lot of code, and all it does now is issue warnings.
> It is still around from the early days of spin_table support.  

That sounds fine to me.

> As for memory nodes, we currently look at the dt, then fall back
> to iomem. We could switch the order, iomem then dt, but then
> those just issue dbgprintf's.

Sure.

> > > +int arm64_process_image_header(const struct arm64_image_header *h)
> > > +{
> > > +#if !defined(KERNEL_IMAGE_SIZE)
> > > +# define KERNEL_IMAGE_SIZE (768 * 1024)
> > > +#endif
> > > +
> > > +> > 	> > if (!arm64_header_check_magic(h))
> > > +> > 	> > 	> > return -EINVAL;
> > > +
> > > +> > 	> > if (h->image_size) {
> > > +> > 	> > 	> > arm64_mem.text_offset = le64_to_cpu(h->text_offset);
> > > +> > 	> > 	> > arm64_mem.image_size = le64_to_cpu(h->image_size);
> > > +> > 	> > } else {
> > > +> > 	> > 	> > /* For 3.16 and older kernels. */
> > > +> > 	> > 	> > arm64_mem.text_offset = 0x80000;
> > > +> > 	> > 	> > arm64_mem.image_size = KERNEL_IMAGE_SIZE;
> > > +> > 	> > }
> > > +
> > > +> > 	> > return 0;
> > > +}
> > 
> > A v3.16 defconfig Image with the Linaro 14.09 GCC 4.9 toolchain is
> > 6.3MB, so the chosen value for KERNEL_IMAGE_SIZE is far too small. I'm
> > not sure what to suggest as a better value, however, as I know that some
> > configurations are far bigger than that.
> 
> OK, I'll make it bigger, say 7.  When I set this up I expected
> the distro maintainer to choose KERNEL_IMAGE_SIZE to match their
> needs.

To give some headroom, bumping to 16 or so is probably a safer bet.

Perhaps it's worth logging a warning that we're guessing the effective
image size in this case? That could avoid a lot of head-scratching if
things do end up overlapping.

> > Do we expect to kexec to a v3.16 or earlier kernel, given we need a much
> > newer first kernel to have kexec in the first place? We could mandate
> > having a header with a non-zero image_size (i.e. the target kernel has
> > to be v3.16 or newer).
> 
> Kexec could be installed as a bootloader, and users may want the
> ability to boot older installations, so I think it worthwile to
> have.

Sure. I was under the impression that most distros had chosen v3.16 or
later, but I have no problem with trying to support earlier kernels.

Thanks,
Mark.



More information about the kexec mailing list