There are no exception on 64-bit ARM.
+Booting Guests
+--------------
+
+Xen supports the legacy image header[3], zImage protocol for 32-bit
+ARM Linux[1] and Image protocol defined for ARM64[2].
+
+Until Xen 4.17, in case of legacy image protocol, Xen ignored the load
+address and entry point specified in the header. This has now changed.
+
+Now, it loads the image at the load address provided in the header.
+And the entry point is used as the kernel start address.
+
+A deviation from uboot is that, Xen treats "load address == 0x0" as
+position independent execution (PIE). Thus, Xen will load such an image
+at an address it considers appropriate. Also, user cannot specify the
+entry point of a PIE image since the start address cennot be
+predetermined.
+
+Users who want to use Xen with statically partitioned domains, can provide
+the fixed non zero load address and start address for the dom0/domU kernel.
+The load address and start address specified by the user in the header must
+be within the memory region allocated by Xen.
+
+Also, it is to be noted that if user provides the legacy image header on
+top of zImage or Image header, then Xen uses the attributes of legacy
+image header to determine the load address, entry point, etc.
+
+Known limitation: compressed kernels with a uboot headers are not
+working.
+
Firmware/bootloader requirements
--------------------------------
[2] linux/Documentation/arm64/booting.rst
Latest version: http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/Documentation/arm64/booting.rst
+
+[3] legacy format header
+Latest version: https://source.denx.de/u-boot/u-boot/-/blob/master/include/image.h#L315
+https://linux.die.net/man/1/mkimage
paddr_t load_addr;
#ifdef CONFIG_ARM_64
- if ( info->type == DOMAIN_64BIT )
+ if ( (info->type == DOMAIN_64BIT) && (info->zimage.start == 0) )
return info->mem.bank[0].start + info->zimage.text_offset;
#endif
void *kernel;
int rc;
- info->entry = load_addr;
+ /*
+ * If the image does not have a fixed entry point, then use the load
+ * address as the entry point.
+ */
+ if ( info->entry == 0 )
+ info->entry = load_addr;
place_modules(info, load_addr, load_addr + len);
if ( len > size - sizeof(uimage) )
return -EINVAL;
+ info->zimage.start = be32_to_cpu(uimage.load);
+ info->entry = be32_to_cpu(uimage.ep);
+
+ /*
+ * While uboot considers 0x0 to be a valid load/start address, for Xen
+ * to maintain parity with zImage, we consider 0x0 to denote position
+ * independent image. That means Xen is free to load such an image at
+ * any valid address.
+ */
+ if ( info->zimage.start == 0 )
+ printk(XENLOG_INFO
+ "No load address provided. Xen will decide where to load it.\n");
+ else
+ printk(XENLOG_INFO
+ "Provided load address: %"PRIpaddr" and entry address: %"PRIpaddr"\n",
+ info->zimage.start, info->entry);
+
+ /*
+ * If the image supports position independent execution, then user cannot
+ * provide an entry point as Xen will load such an image at any appropriate
+ * memory address. Thus, we need to return error.
+ */
+ if ( (info->zimage.start == 0) && (info->entry != 0) )
+ {
+ printk(XENLOG_ERR
+ "Entry point cannot be non zero for PIE image.\n");
+ return -EINVAL;
+ }
+
info->zimage.kernel_addr = addr + sizeof(uimage);
info->zimage.len = len;
- info->entry = info->zimage.start;
info->load = kernel_zimage_load;
#ifdef CONFIG_ARM_64
printk(XENLOG_ERR "Unsupported uImage arch type %d\n", uimage.arch);
return -EINVAL;
}
+
+ /*
+ * If there is a uImage header, then we do not parse zImage or zImage64
+ * header. In other words if the user provides a uImage header on top of
+ * zImage or zImage64 header, Xen uses the attributes of uImage header only.
+ * Thus, Xen uses uimage.load attribute to determine the load address and
+ * zimage.text_offset is ignored.
+ */
+ info->zimage.text_offset = 0;
#endif
return 0;
info->zimage.kernel_addr = addr;
info->zimage.len = end - start;
info->zimage.text_offset = zimage.text_offset;
+ info->zimage.start = 0;
info->load = kernel_zimage_load;
u64 kernel_addr, initrd_addr, dtb_addr, size;
int rc;
+ /*
+ * We need to initialize start to 0. This field may be populated during
+ * kernel_xxx_probe() if the image has a fixed entry point (for e.g.
+ * uimage.ep).
+ * We will use this to determine if the image has a fixed entry point or
+ * the load address should be used as the start address.
+ */
+ info->entry = 0;
+
/* domain is NULL only for the hardware domain */
if ( domain == NULL )
{