Add optional build flag to check effective image size
Some targets will have a static-size memory carveout dedicated
to the hypervisor. In those cases, we should assert that the Hafnium
image does fit into the allocated memory. Add this as a toolchain arg
'plat_max_image_size' and add a new assertion into check_elf.py. This
way the build will fail if the image is too big.
Change-Id: Ib7311c49b185685aef167988c9aa2416822a6f28
diff --git a/build/image/check_elf.py b/build/image/check_elf.py
index 1dc0cec..a949e72 100644
--- a/build/image/check_elf.py
+++ b/build/image/check_elf.py
@@ -30,12 +30,19 @@
HF_ROOT = os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
CLANG_ROOT = os.path.join(HF_ROOT, "prebuilts", "linux-x64", "clang")
OBJDUMP = os.path.join(CLANG_ROOT, "bin", "llvm-objdump")
+NM = os.path.join(CLANG_ROOT, "bin", "llvm-nm")
-def check_eret_speculation_barrier(objdump_stdout):
+def check_eret_speculation_barrier(args):
"""
Some ARM64 CPUs speculatively execute instructions after ERET.
Check that every ERET is followed by DSB NSH and ISB.
"""
+
+ objdump_stdout = subprocess\
+ .check_output([ OBJDUMP, "-d", args.input_elf ])\
+ .decode("utf-8")\
+ .splitlines()
+
found_eret = False
STATE_DEFAULT = 1
@@ -68,19 +75,59 @@
if not found_eret:
raise Exception("Could not find any ERET instructions")
+def check_max_image_size(args):
+ """
+ Check that the ELF's effective image size does not exceed maximum
+ allowed image size, if specified in command-line arguments.
+ """
+
+ if args.max_image_size <= 0:
+ return
+
+ nm_stdout = subprocess\
+ .check_output([ NM, args.input_elf ])\
+ .decode("utf-8")\
+ .splitlines()
+
+ COLUMN_COUNT = 3
+ COLUMN_IDX_VALUE = 0
+ COLUMN_IDX_TYPE = 1
+ COLUMN_IDX_NAME = 2
+
+ image_size = None
+ for line in nm_stdout:
+ line = line.split()
+ if len(line) != COLUMN_COUNT:
+ raise Exception(
+ "Unexpected number of columns in NM output")
+
+ if line[COLUMN_IDX_NAME] == "image_size":
+ if line[COLUMN_IDX_TYPE] != "A":
+ raise Exception(
+ "Unexpected type of image_size symbol")
+ image_size = int(line[COLUMN_IDX_VALUE], 16)
+ break
+
+ if image_size is None:
+ raise Exception("Could not find value of image_size symbol")
+ elif image_size > args.max_image_size:
+ raise Exception(
+ "Image size exceeds maximum allowed image size " +
+ "({}B > {}B)".format(image_size, args.max_image_size))
+
def Main():
parser = argparse.ArgumentParser()
parser.add_argument("input_elf",
help="ELF file to analyze")
parser.add_argument("stamp_file",
help="file to be touched if successful")
+ parser.add_argument("--max-image-size",
+ required=False, type=int, default=0,
+ help="maximum allowed image size in bytes")
args = parser.parse_args()
- objdump_stdout = subprocess.check_output([
- OBJDUMP, "-d", args.input_elf ])
- objdump_stdout = objdump_stdout.decode("utf-8").splitlines()
-
- check_eret_speculation_barrier(objdump_stdout)
+ check_eret_speculation_barrier(args)
+ check_max_image_size(args)
# Touch `stamp_file`.
with open(args.stamp_file, "w"):
diff --git a/build/image/image.gni b/build/image/image.gni
index 7860784..1ff8777 100644
--- a/build/image/image.gni
+++ b/build/image/image.gni
@@ -13,6 +13,7 @@
# limitations under the License.
import("//build/toolchain/embedded.gni")
+import("//build/toolchain/platform.gni")
# Build image, link to an ELF file then convert to plain binary.
template("image_binary") {
@@ -73,6 +74,8 @@
args = [
rebase_path(elf_file),
rebase_path(stamp_file),
+ "--max-image-size",
+ "$plat_max_image_size",
]
outputs = [
stamp_file,
diff --git a/build/toolchain/embedded.gni b/build/toolchain/embedded.gni
index fa4aeae..e824202 100644
--- a/build/toolchain/embedded.gni
+++ b/build/toolchain/embedded.gni
@@ -294,6 +294,9 @@
plat_boot_flow = invoker.boot_flow
plat_console = invoker.console
plat_iommu = invoker.iommu
+ if (defined(invoker.max_image_size)) {
+ plat_max_image_size = invoker.max_image_size
+ }
forward_variables_from(invoker.toolchain_args, "*")
}
}
@@ -321,6 +324,7 @@
"gicr_base_address",
"heap_pages",
"max_cpus",
+ "max_image_size",
"max_vms",
"toolchain_args",
])
diff --git a/build/toolchain/platform.gni b/build/toolchain/platform.gni
index 7ff4b5a..6f4df04 100644
--- a/build/toolchain/platform.gni
+++ b/build/toolchain/platform.gni
@@ -35,6 +35,9 @@
# The maximum number of CPUs available on the platform.
plat_max_cpus = 1
+ # The maximum allowed size of Hafnium's image in memory. Zero if don't care.
+ plat_max_image_size = 0
+
# The maximum number of VMs required for the platform.
plat_max_vms = 0
}