Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

resources: add Arm SPEC 2006 Ubuntu 24.04 disk image #53

Draft
wants to merge 1 commit into
base: stable
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
201 changes: 201 additions & 0 deletions src/arm-ubuntu-spec-2006/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
---
title: Linux arm-ubuntu image
tags:
- arm
- fullsystem
layout: default
permalink: resources/arm-ubuntu
shortdoc: >
Resources to build a generic arm-ubuntu disk image.
author: ["Hoa Nguyen", "Kaustav Goswami"]
---

This document provides instructions to create the "arm-ubuntu" image and
points to the gem5 component that would work with the disk image. The
arm-ubuntu disk image is based on Ubuntu's server cloud image for
arm available at (https://cloud-images.ubuntu.com/focal/current/).
The `.bashrc` file would be modified in such a way that it executes
a script passed from the gem5 configuration files (using the `m5 readfile`
instruction).

The instructions for bringing up QEMU emulation are based on
[Ubuntu's Wiki](https://wiki.ubuntu.com/ARM64/QEMU),
and the instructions for creating a cloud disk image are based on
[this guide](https://gist.github.com/oznu/ac9efae7c24fd1f37f1d933254587aa4).
More information about cloud-init can be found
[here](https://cloudinit.readthedocs.io/en/latest/topics/examples.html).

We assume the following directory structure while following the instructions
in this README file:

```
arm-ubuntu/
|___ gem5/ # gem5 source code (to be cloned here)
|
|___ disk-image/
| |___ aarch64-ubuntu.img # The ubuntu disk image should be downloaded and modified here
| |___ shared/ # Auxiliary files needed for disk creation
| | |___ [email protected] # Auto-login script
| |___ arm-ubuntu/
| |___ cloud.txt # the cloud config, to be created
| |___ gem5_init.sh # The script to be appended to .bashrc on the disk image
| |___ post-installation.sh # The script manipulating the disk image
| |___ arm-ubuntu.json # The Packer script
|
|
|___ README.md # This README file
```

## Building the disk image

This requires an ARM cross compiler to be installed. The disk image is a 64-bit
ARM 64 (aarch64) disk image. Therefore, we only focus on the 64-bit version of
the cross compiler. It can be installed by:

```sh
sudo apt-get install g++-10-aarch64-linux-gnu gcc-10-aarch64-linux-gnu
```

In order to build the ARM based Ubuntu disk-image for with gem5, build the m5
utility in `gem5/util/m5` using the following:

```sh
git clone https://gem5.googlesource.com/public/gem5
cd gem5/util/m5
scons build/arm64/out/m5
```

Troubleshooting: You may need to edit the SConscript to point to the correct
cross compiler.
```
...
main['CXX'] = '${CROSS_COMPILE}g++-10'
...
```

# Installing QEMU for aarch64

On the host machine,

```sh
sudo apt-get install qemu-system-arm qemu-efi
```

# Installing cloud utilities

On the host machine,

```sh
sudo apt-get install cloud-utils
```

# Downloading the cloud disk image

In the `arm-ubuntu/disk-image/` directory,

```sh
wget https://cloud-images.ubuntu.com/focal/current/focal-server-cloudimg-arm64.img
```

# Booting the disk image using QEMU

## Generating an SSH key pair
```sh
ssh-keygen -t rsa -b 4096
```
Leave all prompted fields empty and hit enter. This will generate a public and
private key pair in files `~/.ssh/id_rsa` and `~/.ssh/id_rsa.pub`. If your username
is different from what is printed by command `whoami`, then add `-C "<username>*<hostname>"`
to the command:
```sh
ssh-keygen -t rsa -b 4096 -C "<username>*<hostname>"
```

## Making a cloud config file

First, we need a cloud config that will have the authorization information
keys for logging in the machine.

In the `arm-ubuntu/disk-image/arm-ubuntu` directory, create a `cloud.txt` file
with the following content,

```sh
#cloud-config
users:
- name: ubuntu <- change this name to the current user (use `whoami`)
ssh-authorized-keys:
- ssh-rsa AAAAABBCCCCCCCrNJfweeeeee <- insert the rsa key here (typically `cat ~/.ssh/id_rsa.pub`)
sudo: ['ALL=(ALL) NOPASSWD:ALL']
groups: sudo
shell: /bin/bash
homedir: /home/ubuntu <- change this to the home directory of `whoami`
```

* Note: Do not leave stray spaces in the `cloud.txt` file.
* If your username is different from what is printed by command `whoami`, then use that for parameter "name" in cloud.txt

More information about generating an ssh rsa key is available
[here](https://docs.github.com/en/authentication/connecting-to-github-with-ssh/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent#generating-a-new-ssh-key).
You can ignore the GitHub email address part.

## Booting the cloud disk image with the cloud config file
In the `arm-ubuntu/disk-image` directory,

```sh
dd if=/dev/zero of=flash0.img bs=1M count=64
dd if=/usr/share/qemu-efi/QEMU_EFI.fd of=flash0.img conv=notrunc
dd if=/dev/zero of=flash1.img bs=1M count=64
cloud-localds --disk-format qcow2 cloud.img arm-ubuntu/cloud.txt
wget https://releases.linaro.org/components/kernel/uefi-linaro/latest/release/qemu64/QEMU_EFI.fd
qemu-system-aarch64 \
-smp 2 \
-m 1024 \
-M virt \
-cpu cortex-a57 \
-bios QEMU_EFI.fd \
-nographic \
-device virtio-blk-device,drive=image \
-drive if=none,id=image,file=focal-server-cloudimg-arm64.img \
-device virtio-blk-device,drive=cloud \
-drive if=none,id=cloud,file=cloud.img \
-netdev user,id=user0 -device virtio-net-device,netdev=eth0 \
-netdev user,id=eth0,hostfwd=tcp::5555-:22
```

## Manipulating the disk image

When the qemu instance has fully booted, cloud-init has completed, and while it
is still running, we will use Packer to connect to the virtual machine and
manipulate the disk image. Before doing that, we need to add the private key using `ssh-add`.

```sh
ssh-add ~/.ssh/id_rsa
```

If the image was booted in qemu on a port number other than 5555, edit the `ssh_port`
parameter in `arm-ubuntu/arm-ubuntu.json` accordingly. The disk manipulation
process is automated. If your username is different from what is printed by
command `whoami`, then edit `build.sh` and change the value of `USER` to `"<your_username>"`.
Then in the `arm-ubuntu/disk-image/` directory,

```sh
chmod +x build.sh
./build.sh
```

`build.sh` also verifies the cloud.txt and modifies the arm-ubuntu.json
accordingly. The packer script, executed by `build.sh` disables systemd. In
case you need to enable systemd stuff, remove the last two provisioners from
the arm-ubuntu.json file.

Note that after executing the packer script, you will not be able to emulate
this disk image in qemu.

## Preparing the disk image for gem5

We need to finalize the image before we can use it with gem5. This is done by:

```sh
qemu-img convert -f qcow2 -O raw focal-server-cloudimg-arm64.img arm64-ubuntu-focal-server.img
rm focal-server-cloudimg-arm64.img
```
127 changes: 127 additions & 0 deletions src/arm-ubuntu-spec-2006/arm-ubuntu-24-04.pkr.hcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
packer {
required_plugins {
qemu = {
source = "github.com/hashicorp/qemu"
version = "~> 1"
}
}
}

variable "image_name" {
type = string
default = "arm-ubuntu"
}

variable "ssh_password" {
type = string
default = "12345"
}

variable "ssh_username" {
type = string
default = "gem5"
}

source "qemu" "initialize" {
boot_command = [
"c<wait>",
"linux /casper/vmlinuz autoinstall ds=nocloud-net\\;s=http://{{.HTTPIP}}:{{.HTTPPort}}/ --- ",
"<enter><wait>",
"initrd /casper/initrd",
"<enter><wait>",
"boot",
"<enter>",
"<wait>"
]
cpus = "4"
disk_size = "18400"
format = "raw"
headless = "true"
http_directory = "http-24-04"
iso_checksum = "sha256:d2d9986ada3864666e36a57634dfc97d17ad921fa44c56eeaca801e7dab08ad7"
iso_urls = ["https://cdimage.ubuntu.com/releases/24.04/release/ubuntu-24.04-live-server-arm64.iso"]
memory = "8192"
output_directory = "disk-image-24-04"
qemu_binary = "/usr/bin/qemu-system-aarch64"
qemuargs = [ ["-boot", "order=dc"],
["-bios", "./files/flash0.img"],
["-cpu", "host"],
["-enable-kvm"],
["-machine", "virt"],
["-machine", "gic-version=3"],
["-vga", "virtio"],
["-device","virtio-gpu-pci"],
["-device", "qemu-xhci"],
["-device","usb-kbd"],

]
shutdown_command = "echo '${var.ssh_password}'|sudo -S shutdown -P now"
ssh_password = "${var.ssh_password}"
ssh_username = "${var.ssh_username}"
ssh_wait_timeout = "60m"
vm_name = "${var.image_name}"
ssh_handshake_attempts = "1000"
}


build {
sources = ["source.qemu.initialize"]

provisioner "file" {
destination = "/home/gem5/"
source = "files/exit.sh"
}

provisioner "file" {
destination = "/home/gem5/"
source = "files/gem5_init.sh"
}

provisioner "file" {
destination = "/home/gem5/"
source = "files/after_boot.sh"
}

provisioner "file" {
destination = "/home/gem5/"
source = "/home/bees/gem5-bootcamp-private/CPU2006v1.0.1.iso"
}

provisioner "file" {
destination = "/home/gem5/"
source = "files/[email protected]"
}

provisioner "file" {
destination = "/home/gem5/"
source = "files/glob.c"
}

provisioner "file" {
destination = "/home/gem5/"
source = "files/makedepend.SH"
}

provisioner "file" {
destination = "/home/gem5/"
source = "files/md5sum.c"
}

provisioner "file" {
destination = "/home/gem5/"
source = "files/SysV.xs"
}

provisioner "file" {
destination = "/home/gem5/"
source = "files/replace-configs.sh"
}


provisioner "shell" {
execute_command = "echo '${var.ssh_password}' | {{ .Vars }} sudo -E -S bash '{{ .Path }}'"
scripts = ["scripts/post-installation.sh", "scripts/install-spec2006.sh"]
expect_disconnect = true
}

}
27 changes: 27 additions & 0 deletions src/arm-ubuntu-spec-2006/build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
PACKER_VERSION="1.10.0"

if [ ! -f ./packer ]; then
wget https://releases.hashicorp.com/packer/${PACKER_VERSION}/packer_${PACKER_VERSION}_linux_arm64.zip;
unzip packer_${PACKER_VERSION}_linux_arm64.zip;
rm packer_${PACKER_VERSION}_linux_arm64.zip;
fi

# Check if the configuration file variable is provided
if [ -z "$1" ]; then
echo "Usage: $0 <configuration_file>"
exit 1
fi

# Store the configuration file name from the command line argument
config_file="$1"

# Check if the specified configuration file exists
if [ -f "$config_file" ]; then
# Install the needed plugins
PACKER_LOG=1 ./packer init "$config_file"
# Build the image
PACKER_LOG=1 ./packer build "$config_file"
else
echo "Error: Configuration file '$config_file' not found."
exit 1
fi
Loading