Skip to content
Commit 0fdf6818 authored by Alexandru Elisei's avatar Alexandru Elisei
Browse files

arm/arm64: Rework the layout of the RAM payload



kvmtool uses the same memory map for 64bit and 32bit guests, where it tries
to stuff everything in the bottom 256MB: the kernel is at the base of the
IPA space, the DTB is placed at the top of the 256MB window, and directly
below it the initrd.

The restriction on placing everything in the bottom 256MB comes from the
aarch32 boot protocol, where the kernel, DTB and initrd must be placed in a
region covered by the low-memory mapping. The size of the lowmem region
varies based on the kernel-userspace split, which is a Kconfig option, and
on the vmalloc area size, which can be specified for the user on the kernel
command line. Hence kvmtool's choice of using the bottom 256MB as a
reasonable compromise that works well most of the cases.

Sina has reported in private that they were unable to create a 64bit
virtual machine with a 351MB initrd with the error:

Warning: unable to translate host address 0xffff53e8a5fc to guest
Warning: unable to translate guest address 0x0 to host
Fatal: initrd overlaps with kernel image

This is due to the above restriction, which is artificial for arm64:
booting.rst specifices that the kernel and initrd must be placed in the
same 32GB window; it says nothing about the 256MB memory window.

Remove the limitation by reworking where the payload is placed in RAM for
arm64, to conform with booting.rst.

The layout is changed to:

  +-------------------------+ <- top of memory
  |                         |
  ~                         ~
  |                         |
  +-------------------------+ <- top of initrd, if present
  |                         |
  +-------------------------+ <- top of DTB, assumed to be FDT_MAX_SIZE in size
  |                         |
  +-------------------------+ <- top of kernel image
  |                         |
  +-------------------------+ <- start of kernel image, at ram_start + kernel offset
  |                         |
  +-------------------------+ <- ram_start

The DTB location has been changed to be after the kernel to preserve
compatibility with Linux guests prior to v4.2, which, according to
booting.rst, required that the DTB be placed within a 512MB region starting
at the kernel image - kernel offset. With the DTB location changed, and
because the arm64 kernel is not compressed like the arm kernel, the initrd
can now be placed above the DTB.

Along with the memory layout changes, an off-by-one bug in how the limit
address was used is now fixed: limit represents the topmost allowed
address, **inclusive**, but size calculations given to read_file() were
off by one: for example, the maximum kernel size was calculated as limit
- pos, but it should have been limit - pos + 1 to account for the fact
the limit was an inclusive address.

As for the arm memory layout, even though it stays the same, there are some
changes to the function that copies the payloads in guest memory: comments
were added and code was reworked with the aim to improve readability, and
the above mentioned off-by-one bug with the limit was  fixed.

Reported-by: default avatarAbdollahi Sina <s.abdollahi22@imperial.ac.uk>
parent da4cfc3e
Loading
Loading
Loading
Loading
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment