diff --git a/test/e2e/files/Vagrantfile.in b/test/e2e/files/Vagrantfile.in index 7820b142c..693dd7c1c 100644 --- a/test/e2e/files/Vagrantfile.in +++ b/test/e2e/files/Vagrantfile.in @@ -88,7 +88,7 @@ Vagrant.configure("2") do |config| qemu.memory = "QEMU_MEM" qemu.arch = "x86_64" qemu.machine = "QEMU_MACHINE" - qemu.cpu = "host" + qemu.cpu = "QEMU_CPU" qemu.net_device = "virtio-net-pci" qemu.extra_netdev_args = "net=192.168.76.0/24,dhcpstart=192.168.76.9" qemu.ssh_port = SSH_PORT diff --git a/test/e2e/lib/topology2qemuopts.py b/test/e2e/lib/topology2qemuopts.py index b342b6203..1f57fad73 100755 --- a/test/e2e/lib/topology2qemuopts.py +++ b/test/e2e/lib/topology2qemuopts.py @@ -24,6 +24,8 @@ The default is 1. "packages" number of packages. The default is 1. +"cpus-present" number of logical CPUs present in the system. + The default value 0 means "all". NUMA node distances are defined with following keys: "dist-all": [[from0to0, from0to1, ...], [from1to0, from1to1, ...], ...] @@ -108,13 +110,15 @@ def validate(numalist): raise ValueError('expected list containing dicts, got %s' % (type(numalist,).__name__)) valid_keys = set(("mem", "nvmem", "dimm", "cores", "threads", "nodes", "dies", "packages", + "cpus-present", "node-dist", "dist-all", "dist-other-package", "dist-same-package", "dist-same-die")) int_range_keys = {'cores': ('>= 0', lambda v: v >= 0), 'threads': ('> 0', lambda v: v > 0), 'nodes': ('> 0', lambda v: v > 0), 'dies': ('> 0', lambda v: v > 0), - 'packages': ('> 0', lambda v: v > 0)} + 'packages': ('> 0', lambda v: v > 0), + 'cpus-present': ('>= 0', lambda v: v >=0)} for numalistindex, numaspec in enumerate(numalist): for key in numaspec: if not key in valid_keys: @@ -210,12 +214,14 @@ def dists(numalist): return dist_dict def qemuopts(numalist): - machineparam = "-machine pc" + machineparam = "-machine q35,kernel-irqchip=split" + cpuparam = "-cpu host,x2apic=on" numaparams = [] objectparams = [] deviceparams = [] lastnode = -1 lastcpu = -1 + lastcpupresent = -1 lastdie = -1 lastsocket = -1 lastmem = -1 @@ -249,6 +255,7 @@ def qemuopts(numalist): cpucount = int(numaspec.get("cores", 0)) * threadcount # logical cpus per numa node (cores * threads) diecount = int(numaspec.get("dies", 1)) packagecount = int(numaspec.get("packages", 1)) + cpuspresentcount = int(numaspec.get("cpus-present", 0)) memsize = numaspec.get("mem", "0") memdimm = numaspec.get("dimm", "") if memsize != "0": @@ -333,6 +340,10 @@ def qemuopts(numalist): currentnumaparams.append("node,nodeid=%s" % (lastnode,)) currentnumaparams[-1] = currentnumaparams[-1] + (",cpus=%s-%s" % (lastcpu + 1, lastcpu + cpucount)) lastcpu += cpucount + if cpuspresentcount > 0: + lastcpupresent = cpuspresentcount - 1 + else: + lastcpupresent += cpucount numaparams.extend(currentnumaparams) node_node_dist = dists(numalist) for sourcenode in sorted(node_node_dist.keys()): @@ -350,7 +361,7 @@ def qemuopts(numalist): # Don't give dies parameter unless it is absolutely necessary # because it requires Qemu >= 5.0. diesparam = "" - cpuparam = "-smp cpus=%s,threads=%s%s,sockets=%s" % (lastcpu + 1, threadcount, diesparam, lastsocket + 1) + smpparam = "-smp cpus=%s,threads=%s%s,sockets=%s,maxcpus=%s" % (lastcpupresent + 1, threadcount, diesparam, lastsocket + 1, lastcpu + 1) maxmem = siadd(totalmem, totalnvmem) startmem = sisub(sisub(maxmem, unpluggedmem), pluggedmem) memparam = "-m size=%s,slots=%s,maxmem=%s" % (startmem, memslots, maxmem) @@ -362,6 +373,7 @@ def qemuopts(numalist): if separated_output_vars == True: return ("MACHINE:" + machineparam + "|" + "CPU:" + cpuparam + "|" + + "SMP:" + smpparam + "|" + "MEM:" + memparam + "|" + "EXTRA:" + ", ".join(map(lambda x: "\"" + x + "\"", numaparams)) + @@ -373,6 +385,7 @@ def qemuopts(numalist): else: return (machineparam + " " + cpuparam + " " + + smpparam + " " + memparam + " " + " ".join(numaparams) + " " + diff --git a/test/e2e/lib/vm.bash b/test/e2e/lib/vm.bash index f4b5b4428..262b244f8 100644 --- a/test/e2e/lib/vm.bash +++ b/test/e2e/lib/vm.bash @@ -126,11 +126,12 @@ vm-setup() { error "error in topology" fi - MACHINE=$(echo $VM_QEMU_CPUMEM | sed 's/MACHINE:-machine \([^|]*\).*/\1/g') - CPU=$(echo $VM_QEMU_CPUMEM | sed 's/MACHINE:.*CPU:-smp \([^|]*\).*/\1/g') - MEM=$(echo $VM_QEMU_CPUMEM | sed 's/MACHINE:.*CPU:.*MEM:-m \([^|]*\).*/\1/g') - EXTRA_ARGS=$(echo $VM_QEMU_CPUMEM | sed 's/MACHINE:.*CPU:.*MEM:.*EXTRA:\([^|]*\).*/\1/g') - EXTRA_ARGS+="${EXTRA_ARGS:+,} \"-monitor\", \"unix:monitor.sock,server,nowait\"" + local MACHINE=$(echo $VM_QEMU_CPUMEM | sed 's/MACHINE:-machine \([^|]*\).*/\1/g') + local CPU=$(echo $VM_QEMU_CPUMEM | sed 's/MACHINE:.*CPU:-cpu \([^|]*\).*/\1/g') + local SMP=$(echo $VM_QEMU_CPUMEM | sed 's/MACHINE:.*CPU:.*SMP:-smp \([^|]*\).*/\1/g') + local MEM=$(echo $VM_QEMU_CPUMEM | sed 's/MACHINE:.*CPU:.*SMP:.*MEM:-m \([^|]*\).*/\1/g') + local EXTRA_ARGS=$(echo $VM_QEMU_CPUMEM | sed 's/MACHINE:.*CPU:.*SMP:.*MEM:.*EXTRA:\([^|]*\).*/\1/g') + local EXTRA_ARGS+="${EXTRA_ARGS:+,} \"-monitor\", \"unix:monitor.sock,server,nowait\"" case $efi in "") ;; @@ -167,6 +168,7 @@ vm-setup() { if [ "$vagrant_debug" == "1" ]; then echo "MACHINE: $MACHINE" echo "CPU: $CPU" + echo "SMP: $SMP" echo "MEM: $MEM" echo "EXTRA: $EXTRA_ARGS" echo "image: ${distro_img:-vagrant default}" @@ -182,8 +184,9 @@ vm-setup() { sed -e "s/SERVER_NAME/$vmname/g" \ -e "s/DISTRO/$distro_name/g" \ -e "s/QEMU_MACHINE/$MACHINE/" \ + -e "s/QEMU_CPU/$CPU/" \ + -e "s/QEMU_SMP/$SMP/" \ -e "s/QEMU_MEM/$MEM/" \ - -e "s/QEMU_SMP/$CPU/" \ -e "s|QEMU_EXTRA_ARGS|$EXTRA_ARGS|" \ -e "s:QEMU_DIR:$qemu_dir:" \ -e "s|^.*config.vm.box_url.*$|$CUSTOM_IMAGE|g" \ @@ -351,6 +354,42 @@ vm-reboot() { # script API deadline=$_deadline host-wait-vm-ssh-server $_vagrantdir } +vm-cpu-hotplug() { # script API + # Usage: vm-cpu-hotplug SOCKETID COREID THREADID + # + # Hotplug currently unplugged CPU to VM. + # + # Examples: + # vm-cpu-hotplug 0 255 0 + local socketid=$1 + local coreid=$2 + local threadid=$3 + local deviceid="cpu-s$socketid-c$coreid-t$threadid" + if [[ -z "$threadid" ]]; then + error "missing one or more IDs: socket core thread" + return 1 + fi + vm-monitor "device_add driver=host-x86_64-cpu,id=${deviceid},socket-id=${socketid},core-id=${coreid},thread-id=${threadid}" +} + +vm-cpu-hotremove() { # script API + # Usage: vm-cpu-hotremove SOCKETID COREID THREADID + # + # Hotremove currently plugged CPU from VM. + # + # Examples: + # vm-cpu-hotremove 0 255 0 + local socketid=$1 + local coreid=$2 + local threadid=$3 + local deviceid="cpu-s$socketid-c$coreid-t$threadid" + if [[ -z "$threadid" ]]; then + error "missing one or more IDs: socket core thread" + return 1 + fi + vm-monitor "device_del ${deviceid}" +} + vm-mem-hotplug() { # script API # Usage: vm-mem-hotplug MEMORY #