Skip to content

Commit

Permalink
memory/gmap: add test for shadow memory counters
Browse files Browse the repository at this point in the history
KVM records shadow memory events for a nested guest.
Confirm the counters go up.

Signed-off-by: Sebastian Mitterle <[email protected]>
  • Loading branch information
smitterl authored and libvirt-qe committed Nov 21, 2023
1 parent e913c9c commit 0d0f655
Show file tree
Hide file tree
Showing 2 changed files with 146 additions and 0 deletions.
7 changes: 7 additions & 0 deletions libvirt/tests/cfg/memory/gmap.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
- gmap:
type = gmap
start_vm = no
only s390-virtio
variants:
- l3_shadow_table_counters:
l2_mem = 3906250
139 changes: 139 additions & 0 deletions libvirt/tests/src/memory/gmap.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
import logging as log
import os
from pathlib import Path

from avocado.core.exceptions import TestError
from virttest import virsh
from virttest.libvirt_xml import vm_xml
from virttest.utils_misc import cmd_status_output
from virttest.utils_test.libvirt_device_utils import create_fs_xml


logging = log.getLogger('avocado.' + __name__)
cleanup_actions = []


def parent(file_path):
"""
Returns the parent directory of a file path
:param file_path: absolute file path
:return path: absolute path of parent directory
"""
return Path(file_path).parent.absolute()


def get_source_disk_path(vmxml):
"""
Returns the absolute path to a disk image for import.
Assume the boot image is the first disk and an image file.
:param vmxml: VMXML instance
:return: absolute path to the guest's first disk image file
"""
disks = vmxml.get_disk_all()
disk_list = list(disks.values())
first_disk = disk_list[0]
return first_disk.find('source').get('file')


def update_l2_vm(vmxml, l2_mem, target_tag):
"""
Update the L2 VM to run L3 inside from virtiofs
:param vmxml: The VMXML instance
:param l2_mem: The new memory size
:param target_tag: virtiofs mount tag
"""
vmxml.memory = l2_mem
mb = vm_xml.VMMemBackingXML()
mb.access_mode = "shared"
vmxml.mb = mb
vmxml.sync()
fs = create_fs_xml({
"accessmode": "passthrough",
"source": {
"dir": parent(get_source_disk_path(vmxml))
},
"target": {"dir": target_tag},
"binary": {"flock": "off", "posix": "off"}
})
virsh.attach_device(vmxml.vm_name, fs.xml, flagstr="--config", debug=True)


def prepare_l3(vmxml):
"""
Prepares the disk for the L3 guest
:param vmxml: The L2 VMXML instance
"""
l2_disk_path = get_source_disk_path(vmxml)
l3_disk_path = os.path.join(parent(l2_disk_path), "test.qcow2")
cmd = ("qemu-img convert -f qcow2 -O qcow2 -o lazy_refcounts=on"
" {} {}".format(l2_disk_path, l3_disk_path))
cmd_status_output(cmd)
cleanup_actions.append(lambda: os.unlink(l3_disk_path))


def start_l3(session, target_tag):
"""
Mount the shared directory with the image file and start
the L3 guest with the qemu-kvm command
:param session: VM session
:param target_tag: virtiofs mount tag
"""
mount_dir = "/mnt"
cmd = "mount -t virtiofs {} {}".format(target_tag, mount_dir)
cmd_status_output(cmd, session=session)
cmd = ("/usr/libexec/qemu-kvm -m 1024 -smp 1"
" -daemonize {}".format(os.path.join(mount_dir, "test.qcow2")))
s, _ = cmd_status_output(cmd, session=session)
if s:
raise TestError("Couldn't start L3 guest.")


def l1_counters_go_up():
"""
Check that the shadow memory counters go up
"""
base_path = "/sys/kernel/debug/kvm/"
for a in [
"gmap_shadow_reuse",
"gmap_shadow_create",
"gmap_shadow_sg_entry",
"gmap_shadow_pg_entry"
]:
with open(os.path.join(base_path, a), "r") as f:
if f.read().strip() == "0":
return False
return True


def run(test, params, env):
"""
Test kvm counters for L3 shadow memory
"""
vm_name = params.get('main_vm')
vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name)
bkxml = vmxml.copy()
cleanup_actions.append(lambda: bkxml.sync())
vm = env.get_vm(vm_name)
l2_mem = int(params.get("l2_mem", "4096"))
target_tag = "mnt"

try:
update_l2_vm(vmxml, l2_mem, target_tag)
prepare_l3(vmxml)
logging.debug("VMXML: %s", vm_xml.VMXML.new_from_dumpxml(vm_name))
vm.start()
cleanup_actions.append(lambda: vm.destroy())
session = vm.wait_for_login()
cleanup_actions.append(lambda: session.close())
start_l3(session, target_tag)
if not l1_counters_go_up():
test.fail("Gmap counters didn't go up.")
finally:
cleanup_actions.reverse()
for a in cleanup_actions:
a()

0 comments on commit 0d0f655

Please sign in to comment.