On 08/19/2016 04:52 PM, Nathan Rossi wrote:
On Fri, Aug 19, 2016 at 6:20 PM, Robert Yang <[email protected]> wrote:
On 08/19/2016 03:52 PM, Nathan Rossi wrote:
On Fri, Aug 19, 2016 at 4:55 PM, Robert Yang <[email protected]>
wrote:
Previously, runqemu had hard coded machine knowledge, which limited its
usage, for example, qemu can boot genericx86, but runqemu can't, we need
edit runqemu/runqemu-internal a lot if we want to boot genericx86.
Now bsp conf files can set vars to make it can be boot by runqemu, and
qemuboot.bbclass will save these info to DEPLOY_DIR_IMAGE/qemuboot.py.
Please see qemuboot.bbclass' comments on how to set the vars.
-- snip --
+
+
+ def setup_slirp(self):
+ if self.fstype == 'nfs':
+ self.setup_nfs()
+ if self.get('TUNE_ARCH') == 'aarch64':
+ raise Exception("aarch64 doesn't support slirp mode")
This doesn't seem quite right? because slirp works fine with the
qemuzynqmp machine which is aarch64 (based on the patch you provided
for meta-xilinx). This looks to be specific to the qemuarm64 machine?
Yes, thanks for the testing.
When I first tested run qemuzynqmp, the following patch didn't get merged,
so it didn't work with slirp:
commit e5c6a78db46192800669f1b392351f6b52f3e20c
Author: Alistair Francis <[email protected]>
AuthorDate: Wed Jun 15 13:43:23 2016 -0700
Commit: Richard Purdie <[email protected]>
CommitDate: Wed Aug 10 10:45:32 2016 +0100
runqemu: qemuzynqmp: Add Linux boot support
Add support to direct boot Linux instead of just booting u-boot.
And for qemuarm64, the old code:
QEMU_NETWORK_CMD="-netdev tap,id=net0,ifname=$TAP,script=no,downscript=no
-device virtio-net-device,netdev=net0 "
It hardcoded TAP, and didn't work with slirp when I tested it, so I
added the checking to avoid unexpected errors. Does anyone know how
to boot qemuarm64 by slirp, please ?
I was able to boot qemuarm64 with slirp, here is a patch (its a quick
hack specific for qemuarm64).
diff --git a/scripts/runqemu b/scripts/runqemu
index 7633bcb..ccf46a9 100755
--- a/scripts/runqemu
+++ b/scripts/runqemu
@@ -552,8 +552,9 @@ class BaseConfig(object):
if self.fstype == 'nfs':
self.setup_nfs()
self.append('KERNEL_CMDLINE_SCRIPT', ' ip=dhcp')
- self.rootfs_options = '-drive file=%s,if=virtio,format=raw' %
self.rootfs
- self.set('QB_NETWORK_CMD', '')
+ qemu_network_cmd = '-netdev user,id=net0 -device
virtio-net-device,netdev=net0'
+ self.rootfs_options = '-drive
id=disk0,file=%s,if=none,format=raw -device
virtio-blk-device,drive=disk0' % self.rootfs
+ self.set('QB_NETWORK_CMD', qemu_network_cmd)
Cool, this can boot aarch64 bsp, though it fails on other archs'
bsps such as qemuarm, qemux86, we can use QB_SLIRP_CMD as
you suggested to fix the problem.
$ runqemu nographic tmp/deploy/images/qemuarm slirp
[snip]
qemu-system-arm: -device virtio-net-device,netdev=net0: No 'virtio-bus' bus
found for device 'virtio-net-device'
[snip]
def setup_tap(self):
"""Setup tap"""
Note the rootfs_options set, it appears this is in the setup_tap as
well, and is required to get the disk to appear. Might need to
refactor the drive setup into the "setup_final"? or a
setup_disk/rootfs function?
Set rootfs_options in setup_final() was what I had did before, but it
would make code more complicated, the problem is slirp, tap, cpio,
nfs, ext2/3/4, iso and vmdk have different rootfs_options, and plus
aarch64 is special, so if we don't set it when we check each of them,
and move the set to setup_final(), then we have to do the check again.
I tested "runqemu qemuzynqmp slirp" just now, it works, so I will remove
this checking in the repo.
For further work, if there are more bsps which can not be boot by slirp,
maybe we can add a var like QB_SLIRP_SUPPORTED = "0" or "1", and default
to 1, if the bsp sets '0' then error out.
It might be worth having a QB_SLIRP_CMD = "", this would allow
machines to setup the args for slirp/user mode networking and tap
networking separately.
See above, sounds good, will do.
Removed the checking, and updated in the repo:
if self.get('TUNE_ARCH') == 'aarch64':
raise Exception("aarch64 doesn't support slirp mode")
// Robert
Regards,
Nathan
+ self.append('KERNEL_CMDLINE_SCRIPT', ' ip=dhcp')
+ self.rootfs_options = '-drive file=%s,if=virtio,format=raw' %
self.rootfs
+ self.set('QB_NETWORK_CMD', '')
+
+ def setup_tap(self):
+ """Setup tap"""
+
+ # This file is created when runqemu-gen-tapdevs creates a bank
of tap
+ # devices, indicating that the user should not bring up new ones
using
+ # sudo.
+ nosudo_flag = '/etc/runqemu-nosudo'
+ self.qemuifup = shutil.which('runqemu-ifup')
+ self.qemuifdown = shutil.which('runqemu-ifdown')
+ ip = shutil.which('ip')
+ lockdir = "/tmp/qemu-tap-locks"
+
+ if not (self.qemuifup and self.qemuifdown and ip):
+ raise Exception("runqemu-ifup, runqemu-ifdown or ip not
found")
+
+ if not os.path.exists(lockdir):
+ os.mkdir(lockdir)
+
+ cmd = '%s link' % ip
+ logger.info('Running %s...' % cmd)
+ ip_link = subprocess.Popen(cmd, shell=True,
stdout=subprocess.PIPE).stdout.read().decode('utf-8')
+ # Matches line like: 6: tap0: <foo>
+ possibles = re.findall('^[1-9]+: +(tap[0-9]+): <.*', ip_link,
re.M)
+ tap = ""
+ use_preconf_tap = False
+ for p in possibles:
+ lockfile = os.path.join(lockdir, p)
+ if os.path.exists('%s.skip' % lockfile):
+ logger.info('Found %s.skip, skipping %s' % (lockfile,
p))
+ continue
+ if acquire_lock(lockfile):
+ self.lockfile = lockfile
+ tap = p
+ logger.info("Using preconfigured tap device %s" % tap)
+ logger.info("If this is not intended, touch %s.skip to
make runqemu skip %s." %(lockfile, tap))
+ use_preconf_tap = True
+ break
+
+ if not tap:
+ if os.path.exists(nosudo_flag):
+ logger.error("Error: There are no available tap devices
to use for networking,")
+ logger.error("and I see %s exists, so I am not going to
try creating" % nosudo_flag)
+ raise Exception("a new one with sudo.")
+
+ gid = os.getgid()
+ uid = os.getuid()
+ logger.info("Setting up tap interface under sudo")
+ cmd = 'sudo %s %s %s %s' % (self.qemuifup, uid, gid,
self.get('STAGING_DIR_NATIVE'))
+ tap = subprocess.Popen(cmd, shell=True,
stdout=subprocess.PIPE).stdout.read().decode('utf-8')
+ self.cleantap = True
+ logger.info('Created tap: %s' % tap)
+
+ self.tap = tap
+ n0 = tap[3:]
+ n1 = int(n0) * 2 + 1
+ n2 = n1 + 1
+ self.nfs_instance = n0
+ if self.fstype == 'nfs':
+ self.setup_nfs()
+ self.append("KERNEL_CMDLINE_SCRIPT", "
ip=192.168.7.%s::192.168.7.%s:255.255.255.0" % (n2, n1))
+ qemu_tap_cmd = "-net
tap,vlan=0,ifname=%s,script=no,downscript=no" % self.tap
+ self.rootfs_options = '-drive file=%s,if=virtio,format=raw' %
self.rootfs
+ if self.get('TUNE_ARCH') == 'aarch64':
+ qemu_network_cmd = '-netdev
tap,id=net0,ifname=%s,script=no,downscript=no -device
virtio-net-device,netdev=net0' % self.tap
+ self.rootfs_options = '-drive
id=disk0,file=%s,if=none,format=raw -device virtio-blk-device,drive=disk0' %
self.rootfs
+ elif self.get('TUNE_ARCH') == 'powerpc':
+ qemu_network_cmd = '%s ' % qemu_tap_cmd
+ else:
+ qemu_network_cmd = "-net nic,model=virtio %s " %
qemu_tap_cmd
+ if self.vhost_enabled:
+ qemu_network_cmd += ',vhost=on'
+ self.weak_assign('QB_NETWORK_CMD', qemu_network_cmd)
+
+ def setup_network(self):
+ cmd = "stty -g"
+ self.saved_stty = subprocess.Popen(cmd, shell=True,
stdout=subprocess.PIPE).stdout.read().decode('utf-8')
+ if self.slirp_enabled:
+ self.setup_slirp()
+ else:
+ self.setup_tap()
+
+ if self.fstype in ('cpio.gz', 'cpio'):
+ self.set('QB_NETWORK_CMD', '')
+ self.kernel_cmdline = 'root=/dev/ram0 rw debugshell'
+ self.rootfs_options = '-initrd %s' % self.rootfs
+ else:
+ if self.fstype in self.vmtypes:
+ if self.fstype == 'iso':
+ vm_drive = '-cdrom %s' % self.rootfs
+ else:
+ cmd1 = "grep -q 'root=/dev/sd' %s" % self.rootfs
+ cmd2 = "grep -q 'root=/dev/hd' %s" % self.rootfs
+ if subprocess.call(cmd1, shell=True) == 0:
+ logger.info('Using scsi drive')
+ vm_drive = '-drive if=none,id=hd,file=%s -device
virtio-scsi-pci,id=scsi -device scsi-hd,drive=hd' % self.rootfs
+ elif subprocess.call(cmd2, shell=True) == 0:
+ logger.info('Using scsi drive')
+ vm_drive = self.rootfs
+ else:
+ logger.warn("Can't detect drive type %s" %
self.rootfs)
+ logger.warn('Tring to use virtio block drive')
+ vm_drive = '-drive if=virtio,file=%s' %
self.rootfs
+ self.rootfs_options = '%s -no-reboot' % vm_drive
+ self.kernel_cmdline = 'root=%s rw highres=off' %
(self.get('KERNEL_ROOT'))
+
+ if self.fstype == 'nfs':
+ self.rootfs_options = ''
+ k_root = '/dev/nfs nfsroot=%s:%s,%s' % (self.nfs_server,
self.nfs_dir, self.unfs_opts)
+ self.kernel_cmdline = 'root=%s rw highres=off' % k_root
+
+ self.weak_assign('QB_ROOTFS_OPTIONS', self.rootfs_options)
+
+ def setup_final(self):
+ qemu_system = self.get('QB_SYSTEM_NAME')
+ if not qemu_system:
+ raise Exception("Failed to boot, QB_SYSTEM_NAME is NULL!")
+
+ qemu_bin = '%s/%s' % (self.get('STAGING_BINDIR_NATIVE'),
qemu_system)
+ if not os.access(qemu_bin, os.X_OK):
+ raise Exception("No QEMU binary '%s' could be found" %
qemu_bin)
+
+ self.qemu_opt = "%s %s %s %s %s %s" % (qemu_bin,
self.get('QB_NETWORK_CMD'), self.get('QEMU_OPT_SCRIPT'),
self.get('QB_ROOTFS_OPTIONS'), self.get('QB_DTB'),
self.get('QB_OPT_APPEND'))
+
+ if self.serialstdio:
+ logger.info("Interrupt character is '^]'")
+ cmd = "stty intr ^]"
+ subprocess.call(cmd, shell=True)
+
+ first_serial = ""
+ if not re.search("-nographic", self.qemu_opt):
+ first_serial = "-serial mon:vc"
+ # We always want a ttyS1. Since qemu by default adds a serial
+ # port when nodefaults is not specified, it seems that all that
+ # would be needed is to make sure a "-serial" is there. However,
+ # it appears that when "-serial" is specified, it ignores the
+ # default serial port that is normally added. So here we make
+ # sure to add two -serial if there are none. And only one if
+ # there is one -serial already.
+ serial_num = len(re.findall("-serial", self.qemu_opt))
+ if serial_num == 0:
+ self.qemu_opt += " %s %s" % (first_serial,
self.get("QB_SERIAL_OPT"))
+ elif serial_num == 1:
+ self.qemu_opt += " %s" % self.get("QB_SERIAL_OPT")
+
+ def start_qemu(self):
+ if self.kernel:
+ kernel_opts = "-kernel %s -append '%s %s %s'" %
(self.kernel, self.kernel_cmdline, self.get('KERNEL_CMDLINE_SCRIPT'),
self.get('QB_KERNEL_CMDLINE_APPEND'))
+ else:
+ kernel_opts = ""
+ cmd = "%s %s" % (self.qemu_opt, kernel_opts)
+ logger.info('Running %s' % cmd)
+ if subprocess.call(cmd, shell=True) != 0:
+ raise Exception('Failed to run %s' % cmd)
+
+ def cleanup(self):
+ if self.cleantap:
+ cmd = 'sudo %s %s %s' % (self.qemuifdown, self.tap,
self.get('STAGING_DIR_NATIVE'))
+ logger.info('Running %s' % cmd)
+ subprocess.call(cmd, shell=True)
+ if self.lockfile:
+ logger.info("Releasing lockfile of preconfigured tap device
'%s'" % self.tap)
+ release_lock(self.lockfile)
+
+ if self.nfs_running:
+ logger.info("Shutting down the userspace NFS server...")
+ cmd = "runqemu-export-rootfs stop %s" % self.nfs_dir
+ logger.info('Running %s' % cmd)
+ subprocess.call(cmd, shell=True)
+
+ if self.saved_stty:
+ cmd = "stty %s" % self.saved_stty
+ subprocess.call(cmd, shell=True)
+
+ if self.clean_nfs_dir:
+ logger.info('Removing %s' % self.nfs_dir)
+ shutil.rmtree(self.nfs_dir)
+ shutil.rmtree('%s.pseudo_state' % self.nfs_dir)
+
+def main():
+ if len(sys.argv) == 1 or "help" in sys.argv:
+ print_usage()
+ return 0
+ config = BaseConfig()
+ config.check_args()
When it fails to parse the args instead of showing the python
exception info (with call stack, etc), it should show the exception
message and the runqemu usage.
Regards,
Nathan
You may not have seen this comment, since I accidentally put two
"Regards," in my previous email.
Yes, I had missed this, print the full help text seems too more,
I will print "See 'runqemu help' on how to use it"
// Robert
Regards,
Nathan
--
_______________________________________________
Openembedded-core mailing list
[email protected]
http://lists.openembedded.org/mailman/listinfo/openembedded-core