From 778d1f364aea12d66c9169c3a0e4902554aee564 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 27 Jul 2024 10:17:36 -0600 Subject: [PATCH 1/4] driver/qemudriver: Make extra_args, cpu and machine optional At least for x86 devices it is not necessary to provide these arguments. Make them optional. Add an x86 example to the documentation too. Signed-off-by: Simon Glass --- doc/configuration.rst | 13 ++++++++++-- labgrid/driver/qemudriver.py | 39 +++++++++++++++++++++--------------- 2 files changed, 34 insertions(+), 18 deletions(-) diff --git a/doc/configuration.rst b/doc/configuration.rst index 4a3ffea66..ed606860c 100644 --- a/doc/configuration.rst +++ b/doc/configuration.rst @@ -2693,6 +2693,15 @@ Binds to: dtb: 'dtb' nic: 'user' + QEMUDriver: + qemu_bin: qemu-i386 + machine: pc + cpu: core2duo + memory: 2G + extra_args: "-accel kvm" + nic: user,model=virtio-net-pci + disk: disk-image + .. code-block:: yaml tools: @@ -2709,8 +2718,8 @@ Implements: Arguments: - qemu_bin (str): reference to the tools key for the QEMU binary - - machine (str): QEMU machine type - - cpu (str): QEMU cpu type + - machine (str): optional, QEMU machine type + - cpu (str): optional, QEMU cpu type - memory (str): QEMU memory size (ends with M or G) - extra_args (str): optional, extra QEMU arguments, they are passed directly to the QEMU binary - boot_args (str): optional, additional kernel boot argument diff --git a/labgrid/driver/qemudriver.py b/labgrid/driver/qemudriver.py index a9dc0829d..9ae7188b3 100644 --- a/labgrid/driver/qemudriver.py +++ b/labgrid/driver/qemudriver.py @@ -32,10 +32,11 @@ class QEMUDriver(ConsoleExpectMixin, Driver, PowerProtocol, ConsoleProtocol): Args: qemu_bin (str): reference to the tools key for the QEMU binary - machine (str): QEMU machine type - cpu (str): QEMU cpu type memory (str): QEMU memory size (ends with M or G) - extra_args (str): optional, extra QEMU arguments passed directly to the QEMU binary + extra_args (str): optional, extra QEMU arguments passed directly to the + QEMU binary + cpu (str): optional, QEMU cpu type + machine (str): optional, QEMU machine type boot_args (str): optional, additional kernel boot argument kernel (str): optional, reference to the images key for the kernel disk (str): optional, reference to the images key for the disk image @@ -52,11 +53,15 @@ class QEMUDriver(ConsoleExpectMixin, Driver, PowerProtocol, ConsoleProtocol): nic (str): optional, configuration string to pass to QEMU to create a network interface """ qemu_bin = attr.ib(validator=attr.validators.instance_of(str)) - machine = attr.ib(validator=attr.validators.instance_of(str)) - cpu = attr.ib(validator=attr.validators.instance_of(str)) memory = attr.ib(validator=attr.validators.instance_of(str)) extra_args = attr.ib( - default='', + default=None, + validator=attr.validators.optional(attr.validators.instance_of(str))) + cpu = attr.ib( + default=None, + validator=attr.validators.optional(attr.validators.instance_of(str))) + machine = attr.ib( + default=None, validator=attr.validators.optional(attr.validators.instance_of(str))) boot_args = attr.ib( default=None, @@ -161,7 +166,7 @@ def get_qemu_base_args(self): cmd.append( f"if=sd,format={disk_format},file={disk_path},id=mmc0{disk_opts}") boot_args.append("root=/dev/mmcblk0p1 rootfstype=ext4 rootwait") - elif self.machine in ["pc", "q35", "virt"]: + elif self.machine in ["pc", "q35", "virt", None]: cmd.append("-drive") cmd.append( f"if=virtio,format={disk_format},file={disk_path}{disk_opts}") @@ -189,15 +194,17 @@ def get_qemu_base_args(self): cmd.append("-bios") cmd.append( self.target.env.config.get_image_path(self.bios)) - - if "-append" in shlex.split(self.extra_args): - raise ExecutionError("-append in extra_args not allowed, use boot_args instead") - - cmd.extend(shlex.split(self.extra_args)) - cmd.append("-machine") - cmd.append(self.machine) - cmd.append("-cpu") - cmd.append(self.cpu) + if self.extra_args: + if "-append" in shlex.split(self.extra_args): + raise ExecutionError("-append in extra_args not allowed, use boot_args instead") + + cmd.extend(shlex.split(self.extra_args)) + if self.machine: + cmd.append("-machine") + cmd.append(self.machine) + if self.cpu: + cmd.append("-cpu") + cmd.append(self.cpu) cmd.append("-m") cmd.append(self.memory) if self.display == "none": From ab86f1553a4e0d5b5d818c8d05865d66c2871a6d Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 27 Jul 2024 10:17:36 -0600 Subject: [PATCH 2/4] driver/qemudriver: Delay setting of the QEMU arguments These arguments are currently set on activation. Where the driver is being used by a strategy, it may need to set the arguments after that. There is no need to have everything set in stone until the on() method is called, so move it there. For existing users, no functional change is intended. Signed-off-by: Simon Glass --- labgrid/driver/qemudriver.py | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/labgrid/driver/qemudriver.py b/labgrid/driver/qemudriver.py index 9ae7188b3..68813708b 100644 --- a/labgrid/driver/qemudriver.py +++ b/labgrid/driver/qemudriver.py @@ -108,6 +108,7 @@ def __attrs_post_init__(self): self._tempdir = None self._socket = None self._clientsocket = None + self._sockpath = None self._forwarded_ports = {} atexit.register(self._atexit) @@ -238,22 +239,11 @@ def get_qemu_base_args(self): def on_activate(self): self._tempdir = tempfile.mkdtemp(prefix="labgrid-qemu-tmp-") - sockpath = f"{self._tempdir}/serialrw" + self._sockpath = f"{self._tempdir}/serialrw" self._socket = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) - self._socket.bind(sockpath) + self._socket.bind(self._sockpath) self._socket.listen(0) - self._cmd = self.get_qemu_base_args() - - self._cmd.append("-S") - self._cmd.append("-qmp") - self._cmd.append("stdio") - - self._cmd.append("-chardev") - self._cmd.append(f"socket,id=serialsocket,path={sockpath}") - self._cmd.append("-serial") - self._cmd.append("chardev:serialsocket") - def on_deactivate(self): if self.status: self.off() @@ -262,6 +252,7 @@ def on_deactivate(self): self._clientsocket = None self._socket.close() self._socket = None + self._sockpath = None shutil.rmtree(self._tempdir) @step() @@ -270,6 +261,17 @@ def on(self): afterwards start the emulator using a QMP Command""" if self.status: return + self._cmd = self.get_qemu_base_args() + + self._cmd.append("-S") + self._cmd.append("-qmp") + self._cmd.append("stdio") + + self._cmd.append("-chardev") + self._cmd.append(f"socket,id=serialsocket,path={self._sockpath}") + self._cmd.append("-serial") + self._cmd.append("chardev:serialsocket") + self.logger.debug("Starting with: %s", self._cmd) self._child = subprocess.Popen( self._cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE) From d386477c7da956e5015e465d9cc0b0101fdcd08e Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 27 Jul 2024 10:17:36 -0600 Subject: [PATCH 3/4] driver/qemudriver: Allow the BIOS filename to be changed The U-Boot strategy will need to provide the filename of the BIOS directly when booting U-Boot on QEMU. Add a method to support this. Signed-off-by: Simon Glass --- labgrid/driver/qemudriver.py | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/labgrid/driver/qemudriver.py b/labgrid/driver/qemudriver.py index 68813708b..baf863539 100644 --- a/labgrid/driver/qemudriver.py +++ b/labgrid/driver/qemudriver.py @@ -1,5 +1,6 @@ """The QEMUDriver implements a driver to use a QEMU target""" import atexit +import os import select import shlex import shutil @@ -133,6 +134,17 @@ def get_qemu_version(self, qemu_bin): return (int(m.group('major')), int(m.group('minor')), int(m.group('micro'))) + def set_bios(self, bios): + """Set the filename of the bios + + This can be used by strategies to set the bios filename, overriding the + value provided in the environment. + + Args: + bios (str): New bios filename + """ + self.bios = bios + def get_qemu_base_args(self): """Returns the base command line used for Qemu without the options related to QMP. These options can be used to start an interactive @@ -193,8 +205,10 @@ def get_qemu_base_args(self): f"if=pflash,format=raw,file={self.target.env.config.get_image_path(self.flash)},id=nor0") # pylint: disable=line-too-long if self.bios is not None: cmd.append("-bios") - cmd.append( - self.target.env.config.get_image_path(self.bios)) + if os.path.exists(self.bios): + cmd.append(self.bios) + else: + cmd.append(self.target.env.config.get_image_path(self.bios)) if self.extra_args: if "-append" in shlex.split(self.extra_args): raise ExecutionError("-append in extra_args not allowed, use boot_args instead") From a46870d4389cff7c1a471859dc8395fc480b0347 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 28 Aug 2024 10:56:13 -0600 Subject: [PATCH 4/4] driver/qemudriver: Report an error if QEMU is not turned on Rather than provide a strange exception, complain when a strategy does not use the QEMU driver properly, perhaps due to user settings. Series-changes: 6 - Add new patch to report an error if QEMU is not turned on Signed-off-by: Simon Glass --- labgrid/driver/qemudriver.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/labgrid/driver/qemudriver.py b/labgrid/driver/qemudriver.py index baf863539..652833f66 100644 --- a/labgrid/driver/qemudriver.py +++ b/labgrid/driver/qemudriver.py @@ -356,6 +356,8 @@ def remove_port_forward(self, proto, local_address, local_port): ) def _read(self, size=1, timeout=10, max_size=None): + if not self._clientsocket: + raise ExecutionError('QEMU has not been started') ready, _, _ = select.select([self._clientsocket], [], [], timeout) if ready: # Collect some more data