diff options
author | Paolo Bonzini <pbonzini@redhat.com> | 2024-04-02 12:26:15 -0400 |
---|---|---|
committer | Paolo Bonzini <pbonzini@redhat.com> | 2024-04-02 12:26:15 -0400 |
commit | 52b761b48f8e23399fafe3834a173c990357b8de (patch) | |
tree | 06f7fe191b277dde269ecb11ff3e089da6f2aff9 /tools/testing | |
parent | 0d1756482e66f326eb65fe08eed24ce2efabb168 (diff) | |
parent | d96c66ab9fb3ad8b243669cf6b41e68d0f7f9ecd (diff) | |
download | linux-52b761b48f8e23399fafe3834a173c990357b8de.tar.gz linux-52b761b48f8e23399fafe3834a173c990357b8de.tar.bz2 linux-52b761b48f8e23399fafe3834a173c990357b8de.zip |
Merge tag 'kvmarm-fixes-6.9-1' of git://git.kernel.org/pub/scm/linux/kernel/git/kvmarm/kvmarm into HEAD
KVM/arm64 fixes for 6.9, part #1
- Ensure perf events programmed to count during guest execution
are actually enabled before entering the guest in the nVHE
configuration.
- Restore out-of-range handler for stage-2 translation faults.
- Several fixes to stage-2 TLB invalidations to avoid stale
translations, possibly including partial walk caches.
- Fix early handling of architectural VHE-only systems to ensure E2H is
appropriately set.
- Correct a format specifier warning in the arch_timer selftest.
- Make the KVM banner message correctly handle all of the possible
configurations.
Diffstat (limited to 'tools/testing')
18 files changed, 747 insertions, 100 deletions
diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl index 829f5bdfd2e4..eb31cd9c977b 100755 --- a/tools/testing/ktest/ktest.pl +++ b/tools/testing/ktest/ktest.pl @@ -792,13 +792,13 @@ sub process_variables { my $retval = ""; # We want to check for '\', and it is just easier - # to check the previous characet of '$' and not need + # to check the previous character of '$' and not need # to worry if '$' is the first character. By adding # a space to $value, we can just check [^\\]\$ and # it will still work. $value = " $value"; - while ($value =~ /(.*?[^\\])\$\{(.*?)\}(.*)/) { + while ($value =~ /(.*?[^\\])\$\{([^\{]*?)\}(.*)/) { my $begin = $1; my $var = $2; my $end = $3; @@ -818,16 +818,20 @@ sub process_variables { # we simple convert to 0 $retval = "${retval}0"; } else { - # put back the origin piece. - $retval = "$retval\$\{$var\}"; + # put back the origin piece, but with $#### to not reprocess it + $retval = "$retval\$####\{$var\}"; # This could be an option that is used later, save # it so we don't warn if this option is not one of # ktests options. $used_options{$var} = 1; } - $value = $end; + $value = "$retval$end"; + $retval = ""; } - $retval = "$retval$value"; + $retval = $value; + + # Convert the saved variables with $####{var} back to ${var} + $retval =~ s/\$####/\$/g; # remove the space added in the beginning $retval =~ s/ //; @@ -843,6 +847,7 @@ sub set_value { if ($lvalue =~ /^(TEST|BISECT|CONFIG_BISECT)_TYPE(\[.*\])?$/ && $prvalue !~ /^(config_|)bisect$/ && $prvalue !~ /^build$/ && + $prvalue !~ /^make_warnings_file$/ && $buildonly) { # Note if a test is something other than build, then we diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Makefile index d117e8a96ded..e1504833654d 100644 --- a/tools/testing/selftests/Makefile +++ b/tools/testing/selftests/Makefile @@ -13,6 +13,7 @@ TARGETS += core TARGETS += cpufreq TARGETS += cpu-hotplug TARGETS += damon +TARGETS += devices TARGETS += dmabuf-heaps TARGETS += drivers/dma-buf TARGETS += drivers/s390x/uvdevice diff --git a/tools/testing/selftests/devices/Makefile b/tools/testing/selftests/devices/Makefile new file mode 100644 index 000000000000..ca29249b30c3 --- /dev/null +++ b/tools/testing/selftests/devices/Makefile @@ -0,0 +1,4 @@ +TEST_PROGS := test_discoverable_devices.py +TEST_FILES := boards ksft.py + +include ../lib.mk diff --git a/tools/testing/selftests/devices/boards/Dell Inc.,XPS 13 9300.yaml b/tools/testing/selftests/devices/boards/Dell Inc.,XPS 13 9300.yaml new file mode 100644 index 000000000000..ff932eb19f0b --- /dev/null +++ b/tools/testing/selftests/devices/boards/Dell Inc.,XPS 13 9300.yaml @@ -0,0 +1,40 @@ +# SPDX-License-Identifier: GPL-2.0 +# +# This is the device definition for the XPS 13 9300. +# The filename "Dell Inc.,XPS 13 9300" was chosen following the format +# "Vendor,Product", where Vendor comes from +# /sys/devices/virtual/dmi/id/sys_vendor, and Product comes from +# /sys/devices/virtual/dmi/id/product_name. +# +# See google,spherion.yaml for more information. +# +- type: pci-controller + # This machine has a single PCI host controller so it's valid to not have any + # key to identify the controller. If it had more than one controller, the UID + # of the controller from ACPI could be used to distinguish as follows: + #acpi-uid: 0 + devices: + - path: 14.0 + type: usb-controller + usb-version: 2 + devices: + - path: 9 + name: camera + interfaces: [0, 1, 2, 3] + - path: 10 + name: bluetooth + interfaces: [0, 1] + - path: 2.0 + name: gpu + - path: 4.0 + name: thermal + - path: 12.0 + name: sensors + - path: 14.3 + name: wifi + - path: 1d.0/0.0 + name: ssd + - path: 1d.7/0.0 + name: sdcard-reader + - path: 1f.3 + name: audio diff --git a/tools/testing/selftests/devices/boards/google,spherion.yaml b/tools/testing/selftests/devices/boards/google,spherion.yaml new file mode 100644 index 000000000000..17157ecd8c14 --- /dev/null +++ b/tools/testing/selftests/devices/boards/google,spherion.yaml @@ -0,0 +1,50 @@ +# SPDX-License-Identifier: GPL-2.0 +# +# This is the device definition for the Google Spherion Chromebook. +# The filename "google,spherion" comes from the Devicetree compatible, so this +# file will be automatically used when the test is run on that machine. +# +# The top-level is a list of controllers, either for USB or PCI(e). +# Every controller needs to have a 'type' key set to either 'usb-controller' or +# 'pci-controller'. +# Every controller needs to be uniquely identified on the platform. To achieve +# this, several optional keys can be used: +# - dt-mmio: identify the MMIO address of the controller as defined in the +# Devicetree. +# - usb-version: for USB controllers to differentiate between USB3 and USB2 +# buses sharing the same controller. +# - acpi-uid: _UID property of the controller as supplied by the ACPI. Useful to +# distinguish between multiple PCI host controllers. +# +# The 'devices' key defines a list of devices that are accessible under that +# controller. A device might be a leaf device or another controller (see +# 'Dell Inc.,XPS 13 9300.yaml'). +# +# The 'path' key is needed for every child device (that is, not top-level) to +# define how to reach this device from the parent controller. For USB devices it +# follows the format \d(.\d)* and denotes the port in the hub at each level in +# the USB topology. For PCI devices it follows the format \d.\d(/\d.\d)* +# denoting the device (identified by device-function pair) at each level in the +# PCI topology. +# +# The 'name' key is used in the leaf devices to name the device for clarity in +# the test output. +# +# For USB leaf devices, the 'interfaces' key should contain a list of the +# interfaces in that device that should be bound to a driver. +# +- type: usb-controller + dt-mmio: 11200000 + usb-version: 2 + devices: + - path: 1.4.1 + interfaces: [0, 1] + name: camera + - path: 1.4.2 + interfaces: [0, 1] + name: bluetooth +- type: pci-controller + dt-mmio: 11230000 + devices: + - path: 0.0/0.0 + name: wifi diff --git a/tools/testing/selftests/devices/ksft.py b/tools/testing/selftests/devices/ksft.py new file mode 100644 index 000000000000..cd89fb2bc10e --- /dev/null +++ b/tools/testing/selftests/devices/ksft.py @@ -0,0 +1,90 @@ +# SPDX-License-Identifier: GPL-2.0 +# +# Copyright (c) 2023 Collabora Ltd +# +# Kselftest helpers for outputting in KTAP format. Based on kselftest.h. +# + +import sys + +ksft_cnt = {"pass": 0, "fail": 0, "skip": 0} +ksft_num_tests = 0 +ksft_test_number = 1 + +KSFT_PASS = 0 +KSFT_FAIL = 1 +KSFT_SKIP = 4 + + +def print_header(): + print("TAP version 13") + + +def set_plan(num_tests): + global ksft_num_tests + ksft_num_tests = num_tests + print("1..{}".format(num_tests)) + + +def print_cnts(): + print( + f"# Totals: pass:{ksft_cnt['pass']} fail:{ksft_cnt['fail']} xfail:0 xpass:0 skip:{ksft_cnt['skip']} error:0" + ) + + +def print_msg(msg): + print(f"# {msg}") + + +def _test_print(result, description, directive=None): + if directive: + directive_str = f"# {directive}" + else: + directive_str = "" + + global ksft_test_number + print(f"{result} {ksft_test_number} {description} {directive_str}") + ksft_test_number += 1 + + +def test_result_pass(description): + _test_print("ok", description) + ksft_cnt["pass"] += 1 + + +def test_result_fail(description): + _test_print("not ok", description) + ksft_cnt["fail"] += 1 + + +def test_result_skip(description): + _test_print("ok", description, "SKIP") + ksft_cnt["skip"] += 1 + + +def test_result(condition, description=""): + if condition: + test_result_pass(description) + else: + test_result_fail(description) + + +def finished(): + if ksft_cnt["pass"] == ksft_num_tests: + exit_code = KSFT_PASS + else: + exit_code = KSFT_FAIL + + print_cnts() + + sys.exit(exit_code) + + +def exit_fail(): + print_cnts() + sys.exit(KSFT_FAIL) + + +def exit_pass(): + print_cnts() + sys.exit(KSFT_PASS) diff --git a/tools/testing/selftests/devices/test_discoverable_devices.py b/tools/testing/selftests/devices/test_discoverable_devices.py new file mode 100755 index 000000000000..fbae8deb593d --- /dev/null +++ b/tools/testing/selftests/devices/test_discoverable_devices.py @@ -0,0 +1,318 @@ +#!/usr/bin/python3 +# SPDX-License-Identifier: GPL-2.0 +# +# Copyright (c) 2023 Collabora Ltd +# +# This script tests for presence and driver binding of devices from discoverable +# buses (ie USB, PCI). +# +# The per-platform YAML file defining the devices to be tested is stored inside +# the boards/ directory and chosen based on DT compatible or DMI IDs (sys_vendor +# and product_name). +# +# See boards/google,spherion.yaml and boards/'Dell Inc.,XPS 13 9300.yaml' for +# the description and examples of the file structure and vocabulary. +# + +import glob +import ksft +import os +import re +import sys +import yaml + +pci_controllers = [] +usb_controllers = [] + +sysfs_usb_devices = "/sys/bus/usb/devices/" + + +def find_pci_controller_dirs(): + sysfs_devices = "/sys/devices" + pci_controller_sysfs_dir = "pci[0-9a-f]{4}:[0-9a-f]{2}" + + dir_regex = re.compile(pci_controller_sysfs_dir) + for path, dirs, _ in os.walk(sysfs_devices): + for d in dirs: + if dir_regex.match(d): + pci_controllers.append(os.path.join(path, d)) + + +def find_usb_controller_dirs(): + usb_controller_sysfs_dir = "usb[\d]+" + + dir_regex = re.compile(usb_controller_sysfs_dir) + for d in os.scandir(sysfs_usb_devices): + if dir_regex.match(d.name): + usb_controllers.append(os.path.realpath(d.path)) + + +def get_dt_mmio(sysfs_dev_dir): + re_dt_mmio = re.compile("OF_FULLNAME=.*@([0-9a-f]+)") + dt_mmio = None + + # PCI controllers' sysfs don't have an of_node, so have to read it from the + # parent + while not dt_mmio: + try: + with open(os.path.join(sysfs_dev_dir, "uevent")) as f: + dt_mmio = re_dt_mmio.search(f.read()).group(1) + return dt_mmio + except: + pass + sysfs_dev_dir = os.path.dirname(sysfs_dev_dir) + + +def get_acpi_uid(sysfs_dev_dir): + with open(os.path.join(sysfs_dev_dir, "firmware_node", "uid")) as f: + return f.read() + + +def get_usb_version(sysfs_dev_dir): + re_usb_version = re.compile("PRODUCT=.*/(\d)/.*") + with open(os.path.join(sysfs_dev_dir, "uevent")) as f: + return int(re_usb_version.search(f.read()).group(1)) + + +def get_usb_busnum(sysfs_dev_dir): + re_busnum = re.compile("BUSNUM=(.*)") + with open(os.path.join(sysfs_dev_dir, "uevent")) as f: + return int(re_busnum.search(f.read()).group(1)) + + +def find_controller_in_sysfs(controller, parent_sysfs=None): + if controller["type"] == "pci-controller": + controllers = pci_controllers + elif controller["type"] == "usb-controller": + controllers = usb_controllers + + result_controllers = [] + + for c in controllers: + if parent_sysfs and parent_sysfs not in c: + continue + + if controller.get("dt-mmio"): + if str(controller["dt-mmio"]) != get_dt_mmio(c): + continue + + if controller.get("usb-version"): + if controller["usb-version"] != get_usb_version(c): + continue + + if controller.get("acpi-uid"): + if controller["acpi-uid"] != get_acpi_uid(c): + continue + + result_controllers.append(c) + + return result_controllers + + +def is_controller(device): + return device.get("type") and "controller" in device.get("type") + + +def path_to_dir(parent_sysfs, dev_type, path): + if dev_type == "usb-device": + usb_dev_sysfs_fmt = "{}-{}" + busnum = get_usb_busnum(parent_sysfs) + dirname = os.path.join( + sysfs_usb_devices, usb_dev_sysfs_fmt.format(busnum, path) + ) + return [os.path.realpath(dirname)] + else: + pci_dev_sysfs_fmt = "????:??:{}" + path_glob = "" + for dev_func in path.split("/"): + dev_func = dev_func.zfill(4) + path_glob = os.path.join(path_glob, pci_dev_sysfs_fmt.format(dev_func)) + + dir_list = glob.glob(os.path.join(parent_sysfs, path_glob)) + + return dir_list + + +def find_in_sysfs(device, parent_sysfs=None): + if parent_sysfs and device.get("path"): + pathdirs = path_to_dir( + parent_sysfs, device["meta"]["type"], str(device["path"]) + ) + if len(pathdirs) != 1: + # Early return to report error + return pathdirs + pathdir = pathdirs[0] + sysfs_path = os.path.join(parent_sysfs, pathdir) + else: + sysfs_path = parent_sysfs + + if is_controller(device): + return find_controller_in_sysfs(device, sysfs_path) + else: + return [sysfs_path] + + +def check_driver_presence(sysfs_dir, current_node): + if current_node["meta"]["type"] == "usb-device": + usb_intf_fmt = "*-*:*.{}" + + interfaces = [] + for i in current_node["interfaces"]: + interfaces.append((i, usb_intf_fmt.format(i))) + + for intf_num, intf_dir_fmt in interfaces: + test_name = f"{current_node['meta']['pathname']}.{intf_num}.driver" + + intf_dirs = glob.glob(os.path.join(sysfs_dir, intf_dir_fmt)) + if len(intf_dirs) != 1: + ksft.test_result_fail(test_name) + continue + intf_dir = intf_dirs[0] + + driver_link = os.path.join(sysfs_dir, intf_dir, "driver") + ksft.test_result(os.path.isdir(driver_link), test_name) + else: + driver_link = os.path.join(sysfs_dir, "driver") + test_name = current_node["meta"]["pathname"] + ".driver" + ksft.test_result(os.path.isdir(driver_link), test_name) + + +def generate_pathname(device): + pathname = "" + + if device.get("path"): + pathname = str(device["path"]) + + if device.get("type"): + dev_type = device["type"] + if device.get("usb-version"): + dev_type = dev_type.replace("usb", "usb" + str(device["usb-version"])) + if device.get("acpi-uid") is not None: + dev_type = dev_type.replace("pci", "pci" + str(device["acpi-uid"])) + pathname = pathname + "/" + dev_type + + if device.get("dt-mmio"): + pathname += "@" + str(device["dt-mmio"]) + + if device.get("name"): + pathname = pathname + "/" + device["name"] + + return pathname + + +def fill_meta_keys(child, parent=None): + child["meta"] = {} + + if parent: + child["meta"]["type"] = parent["type"].replace("controller", "device") + + pathname = generate_pathname(child) + if parent: + pathname = parent["meta"]["pathname"] + "/" + pathname + child["meta"]["pathname"] = pathname + + +def parse_device_tree_node(current_node, parent_sysfs=None): + if not parent_sysfs: + fill_meta_keys(current_node) + + sysfs_dirs = find_in_sysfs(current_node, parent_sysfs) + if len(sysfs_dirs) != 1: + if len(sysfs_dirs) == 0: + ksft.test_result_fail( + f"Couldn't find in sysfs: {current_node['meta']['pathname']}" + ) + else: + ksft.test_result_fail( + f"Found multiple sysfs entries for {current_node['meta']['pathname']}: {sysfs_dirs}" + ) + return + sysfs_dir = sysfs_dirs[0] + + if not is_controller(current_node): + ksft.test_result( + os.path.exists(sysfs_dir), current_node["meta"]["pathname"] + ".device" + ) + check_driver_presence(sysfs_dir, current_node) + else: + for child_device in current_node["devices"]: + fill_meta_keys(child_device, current_node) + parse_device_tree_node(child_device, sysfs_dir) + + +def count_tests(device_trees): + test_count = 0 + + def parse_node(device): + nonlocal test_count + if device.get("devices"): + for child in device["devices"]: + parse_node(child) + else: + if device.get("interfaces"): + test_count += len(device["interfaces"]) + else: + test_count += 1 + test_count += 1 + + for device_tree in device_trees: + parse_node(device_tree) + + return test_count + + +def get_board_filenames(): + filenames = [] + + platform_compatible_file = "/proc/device-tree/compatible" + if os.path.exists(platform_compatible_file): + with open(platform_compatible_file) as f: + for line in f: + filenames.extend(line.split("\0")) + else: + dmi_id_dir = "/sys/devices/virtual/dmi/id" + vendor_dmi_file = os.path.join(dmi_id_dir, "sys_vendor") + product_dmi_file = os.path.join(dmi_id_dir, "product_name") + + with open(vendor_dmi_file) as f: + vendor = f.read().replace("\n", "") + with open(product_dmi_file) as f: + product = f.read().replace("\n", "") + + filenames = [vendor + "," + product] + + return filenames + + +def run_test(yaml_file): + ksft.print_msg(f"Using board file: {yaml_file}") + + with open(yaml_file) as f: + device_trees = yaml.safe_load(f) + + ksft.set_plan(count_tests(device_trees)) + + for device_tree in device_trees: + parse_device_tree_node(device_tree) + + +find_pci_controller_dirs() +find_usb_controller_dirs() + +ksft.print_header() + +board_file = "" +for board_filename in get_board_filenames(): + full_board_filename = os.path.join("boards", board_filename + ".yaml") + + if os.path.exists(full_board_filename): + board_file = full_board_filename + break + +if not board_file: + ksft.print_msg("No matching board file found") + ksft.exit_fail() + +run_test(board_file) + +ksft.finished() diff --git a/tools/testing/selftests/kvm/aarch64/arch_timer.c b/tools/testing/selftests/kvm/aarch64/arch_timer.c index ddba2c2fb5de..93100b3f1312 100644 --- a/tools/testing/selftests/kvm/aarch64/arch_timer.c +++ b/tools/testing/selftests/kvm/aarch64/arch_timer.c @@ -135,7 +135,7 @@ static void guest_run_stage(struct test_vcpu_shared_data *shared_data, irq_iter = READ_ONCE(shared_data->nr_iter); __GUEST_ASSERT(config_iter + 1 == irq_iter, - "config_iter + 1 = 0x%lx, irq_iter = 0x%lx.\n" + "config_iter + 1 = 0x%x, irq_iter = 0x%x.\n" " Guest timer interrupt was not trigged within the specified\n" " interval, try to increase the error margin by [-e] option.\n", config_iter + 1, irq_iter); diff --git a/tools/testing/selftests/net/forwarding/vxlan_bridge_1d_ipv6.sh b/tools/testing/selftests/net/forwarding/vxlan_bridge_1d_ipv6.sh index a0bb4524e1e9..a603f7b0a08f 100755 --- a/tools/testing/selftests/net/forwarding/vxlan_bridge_1d_ipv6.sh +++ b/tools/testing/selftests/net/forwarding/vxlan_bridge_1d_ipv6.sh @@ -354,7 +354,7 @@ __ping_ipv4() # Send 100 packets and verify that at least 100 packets hit the rule, # to overcome ARP noise. - PING_COUNT=100 PING_TIMEOUT=11 ping_do $dev $dst_ip + PING_COUNT=100 PING_TIMEOUT=20 ping_do $dev $dst_ip check_err $? "Ping failed" tc_check_at_least_x_packets "dev $rp1 egress" 101 10 100 @@ -410,7 +410,7 @@ __ping_ipv6() # Send 100 packets and verify that at least 100 packets hit the rule, # to overcome neighbor discovery noise. - PING_COUNT=100 PING_TIMEOUT=11 ping6_do $dev $dst_ip + PING_COUNT=100 PING_TIMEOUT=20 ping6_do $dev $dst_ip check_err $? "Ping failed" tc_check_at_least_x_packets "dev $rp1 egress" 101 100 diff --git a/tools/testing/selftests/net/forwarding/vxlan_bridge_1q_ipv6.sh b/tools/testing/selftests/net/forwarding/vxlan_bridge_1q_ipv6.sh index d880df89bc8b..e83fde79f40d 100755 --- a/tools/testing/selftests/net/forwarding/vxlan_bridge_1q_ipv6.sh +++ b/tools/testing/selftests/net/forwarding/vxlan_bridge_1q_ipv6.sh @@ -457,7 +457,7 @@ __ping_ipv4() # Send 100 packets and verify that at least 100 packets hit the rule, # to overcome ARP noise. - PING_COUNT=100 PING_TIMEOUT=11 ping_do $dev $dst_ip + PING_COUNT=100 PING_TIMEOUT=20 ping_do $dev $dst_ip check_err $? "Ping failed" tc_check_at_least_x_packets "dev $rp1 egress" 101 10 100 @@ -522,7 +522,7 @@ __ping_ipv6() # Send 100 packets and verify that at least 100 packets hit the rule, # to overcome neighbor discovery noise. - PING_COUNT=100 PING_TIMEOUT=11 ping6_do $dev $dst_ip + PING_COUNT=100 PING_TIMEOUT=20 ping6_do $dev $dst_ip check_err $? "Ping failed" tc_check_at_least_x_packets "dev $rp1 egress" 101 100 diff --git a/tools/testing/selftests/net/udpgro_fwd.sh b/tools/testing/selftests/net/udpgro_fwd.sh index 9cd5e885e91f..380cb15e942e 100755 --- a/tools/testing/selftests/net/udpgro_fwd.sh +++ b/tools/testing/selftests/net/udpgro_fwd.sh @@ -217,6 +217,7 @@ for family in 4 6; do cleanup create_ns + ip netns exec $NS_DST ethtool -K veth$DST generic-receive-offload on ip netns exec $NS_DST ethtool -K veth$DST rx-gro-list on run_test "GRO frag list" $BM_NET$DST 1 0 cleanup @@ -227,6 +228,7 @@ for family in 4 6; do # use NAT to circumvent GRO FWD check create_ns ip -n $NS_DST addr add dev veth$DST $BM_NET$DST_NAT/$SUFFIX + ip netns exec $NS_DST ethtool -K veth$DST generic-receive-offload on ip netns exec $NS_DST ethtool -K veth$DST rx-udp-gro-forwarding on ip netns exec $NS_DST $IPT -t nat -I PREROUTING -d $BM_NET$DST_NAT \ -j DNAT --to-destination $BM_NET$DST @@ -240,6 +242,7 @@ for family in 4 6; do cleanup create_vxlan_pair + ip netns exec $NS_DST ethtool -K veth$DST generic-receive-offload on ip netns exec $NS_DST ethtool -K veth$DST rx-gro-list on run_test "GRO frag list over UDP tunnel" $OL_NET$DST 1 1 cleanup @@ -247,6 +250,7 @@ for family in 4 6; do # use NAT to circumvent GRO FWD check create_vxlan_pair ip -n $NS_DST addr add dev $VXDEV$DST $OL_NET$DST_NAT/$SUFFIX + ip netns exec $NS_DST ethtool -K veth$DST generic-receive-offload on ip netns exec $NS_DST ethtool -K veth$DST rx-udp-gro-forwarding on ip netns exec $NS_DST $IPT -t nat -I PREROUTING -d $OL_NET$DST_NAT \ -j DNAT --to-destination $OL_NET$DST diff --git a/tools/testing/selftests/net/veth.sh b/tools/testing/selftests/net/veth.sh index 5ae85def0739..3a394b43e274 100755 --- a/tools/testing/selftests/net/veth.sh +++ b/tools/testing/selftests/net/veth.sh @@ -249,9 +249,9 @@ cleanup create_ns ip -n $NS_DST link set dev veth$DST up ip -n $NS_DST link set dev veth$DST xdp object ${BPF_FILE} section xdp -chk_gro_flag "gro vs xdp while down - gro flag on" $DST on +chk_gro_flag "gro vs xdp while down - gro flag off" $DST off ip -n $NS_DST link set dev veth$DST down -chk_gro_flag " - after down" $DST on +chk_gro_flag " - after down" $DST off ip -n $NS_DST link set dev veth$DST xdp off chk_gro_flag " - after xdp off" $DST off ip -n $NS_DST link set dev veth$DST up @@ -261,6 +261,21 @@ chk_gro_flag " - after peer xdp" $DST off cleanup create_ns +ip -n $NS_DST link set dev veth$DST up +ip -n $NS_DST link set dev veth$DST xdp object ${BPF_FILE} section xdp +ip netns exec $NS_DST ethtool -K veth$DST generic-receive-offload on +chk_gro_flag "gro vs xdp while down - gro flag on" $DST on +ip -n $NS_DST link set dev veth$DST down +chk_gro_flag " - after down" $DST on +ip -n $NS_DST link set dev veth$DST xdp off +chk_gro_flag " - after xdp off" $DST on +ip -n $NS_DST link set dev veth$DST up +chk_gro_flag " - after up" $DST on +ip -n $NS_SRC link set dev veth$SRC xdp object ${BPF_FILE} section xdp +chk_gro_flag " - after peer xdp" $DST on +cleanup + +create_ns chk_channels "default channels" $DST 1 1 ip -n $NS_DST link set dev veth$DST down @@ -327,11 +342,14 @@ if [ $CPUS -gt 2 ]; then fi ip -n $NS_DST link set dev veth$DST xdp object ${BPF_FILE} section xdp 2>/dev/null -chk_gro_flag "with xdp attached - gro flag" $DST on +chk_gro_flag "with xdp attached - gro flag" $DST off chk_gro_flag " - peer gro flag" $SRC off chk_tso_flag " - tso flag" $SRC off chk_tso_flag " - peer tso flag" $DST on ip netns exec $NS_DST ethtool -K veth$DST rx-udp-gro-forwarding on +chk_gro " - no aggregation" 10 +ip netns exec $NS_DST ethtool -K veth$DST generic-receive-offload on +chk_gro_flag " - gro flag with GRO on" $DST on chk_gro " - aggregation" 1 diff --git a/tools/testing/selftests/riscv/mm/mmap_bottomup.c b/tools/testing/selftests/riscv/mm/mmap_bottomup.c index 1757d19ca89b..7f7d3eb8b9c9 100644 --- a/tools/testing/selftests/riscv/mm/mmap_bottomup.c +++ b/tools/testing/selftests/riscv/mm/mmap_bottomup.c @@ -6,30 +6,9 @@ TEST(infinite_rlimit) { -// Only works on 64 bit -#if __riscv_xlen == 64 - struct addresses mmap_addresses; - EXPECT_EQ(BOTTOM_UP, memory_layout()); - do_mmaps(&mmap_addresses); - - EXPECT_NE(MAP_FAILED, mmap_addresses.no_hint); - EXPECT_NE(MAP_FAILED, mmap_addresses.on_37_addr); - EXPECT_NE(MAP_FAILED, mmap_addresses.on_38_addr); - EXPECT_NE(MAP_FAILED, mmap_addresses.on_46_addr); - EXPECT_NE(MAP_FAILED, mmap_addresses.on_47_addr); - EXPECT_NE(MAP_FAILED, mmap_addresses.on_55_addr); - EXPECT_NE(MAP_FAILED, mmap_addresses.on_56_addr); - - EXPECT_GT(1UL << 47, (unsigned long)mmap_addresses.no_hint); - EXPECT_GT(1UL << 38, (unsigned long)mmap_addresses.on_37_addr); - EXPECT_GT(1UL << 38, (unsigned long)mmap_addresses.on_38_addr); - EXPECT_GT(1UL << 38, (unsigned long)mmap_addresses.on_46_addr); - EXPECT_GT(1UL << 47, (unsigned long)mmap_addresses.on_47_addr); - EXPECT_GT(1UL << 47, (unsigned long)mmap_addresses.on_55_addr); - EXPECT_GT(1UL << 56, (unsigned long)mmap_addresses.on_56_addr); -#endif + TEST_MMAPS; } TEST_HARNESS_MAIN diff --git a/tools/testing/selftests/riscv/mm/mmap_default.c b/tools/testing/selftests/riscv/mm/mmap_default.c index c63c60b9397e..2ba3ec990006 100644 --- a/tools/testing/selftests/riscv/mm/mmap_default.c +++ b/tools/testing/selftests/riscv/mm/mmap_default.c @@ -6,30 +6,9 @@ TEST(default_rlimit) { -// Only works on 64 bit -#if __riscv_xlen == 64 - struct addresses mmap_addresses; - EXPECT_EQ(TOP_DOWN, memory_layout()); - do_mmaps(&mmap_addresses); - - EXPECT_NE(MAP_FAILED, mmap_addresses.no_hint); - EXPECT_NE(MAP_FAILED, mmap_addresses.on_37_addr); - EXPECT_NE(MAP_FAILED, mmap_addresses.on_38_addr); - EXPECT_NE(MAP_FAILED, mmap_addresses.on_46_addr); - EXPECT_NE(MAP_FAILED, mmap_addresses.on_47_addr); - EXPECT_NE(MAP_FAILED, mmap_addresses.on_55_addr); - EXPECT_NE(MAP_FAILED, mmap_addresses.on_56_addr); - - EXPECT_GT(1UL << 47, (unsigned long)mmap_addresses.no_hint); - EXPECT_GT(1UL << 38, (unsigned long)mmap_addresses.on_37_addr); - EXPECT_GT(1UL << 38, (unsigned long)mmap_addresses.on_38_addr); - EXPECT_GT(1UL << 38, (unsigned long)mmap_addresses.on_46_addr); - EXPECT_GT(1UL << 47, (unsigned long)mmap_addresses.on_47_addr); - EXPECT_GT(1UL << 47, (unsigned long)mmap_addresses.on_55_addr); - EXPECT_GT(1UL << 56, (unsigned long)mmap_addresses.on_56_addr); -#endif + TEST_MMAPS; } TEST_HARNESS_MAIN diff --git a/tools/testing/selftests/riscv/mm/mmap_test.h b/tools/testing/selftests/riscv/mm/mmap_test.h index 2e0db9c5be6c..3b29ca3bb3d4 100644 --- a/tools/testing/selftests/riscv/mm/mmap_test.h +++ b/tools/testing/selftests/riscv/mm/mmap_test.h @@ -4,63 +4,86 @@ #include <sys/mman.h> #include <sys/resource.h> #include <stddef.h> +#include <strings.h> +#include "../../kselftest_harness.h" #define TOP_DOWN 0 #define BOTTOM_UP 1 -struct addresses { - int *no_hint; - int *on_37_addr; - int *on_38_addr; - int *on_46_addr; - int *on_47_addr; - int *on_55_addr; - int *on_56_addr; +#if __riscv_xlen == 64 +uint64_t random_addresses[] = { + 0x19764f0d73b3a9f0, 0x016049584cecef59, 0x3580bdd3562f4acd, + 0x1164219f20b17da0, 0x07d97fcb40ff2373, 0x76ec528921272ee7, + 0x4dd48c38a3de3f70, 0x2e11415055f6997d, 0x14b43334ac476c02, + 0x375a60795aff19f6, 0x47f3051725b8ee1a, 0x4e697cf240494a9f, + 0x456b59b5c2f9e9d1, 0x101724379d63cb96, 0x7fe9ad31619528c1, + 0x2f417247c495c2ea, 0x329a5a5b82943a5e, 0x06d7a9d6adcd3827, + 0x327b0b9ee37f62d5, 0x17c7b1851dfd9b76, 0x006ebb6456ec2cd9, + 0x00836cd14146a134, 0x00e5c4dcde7126db, 0x004c29feadf75753, + 0x00d8b20149ed930c, 0x00d71574c269387a, 0x0006ebe4a82acb7a, + 0x0016135df51f471b, 0x00758bdb55455160, 0x00d0bdd949b13b32, + 0x00ecea01e7c5f54b, 0x00e37b071b9948b1, 0x0011fdd00ff57ab3, + 0x00e407294b52f5ea, 0x00567748c200ed20, 0x000d073084651046, + 0x00ac896f4365463c, 0x00eb0d49a0b26216, 0x0066a2564a982a31, + 0x002e0d20237784ae, 0x0000554ff8a77a76, 0x00006ce07a54c012, + 0x000009570516d799, 0x00000954ca15b84d, 0x0000684f0d453379, + 0x00002ae5816302b5, 0x0000042403fb54bf, 0x00004bad7392bf30, + 0x00003e73bfa4b5e3, 0x00005442c29978e0, 0x00002803f11286b6, + 0x000073875d745fc6, 0x00007cede9cb8240, 0x000027df84cc6a4f, + 0x00006d7e0e74242a, 0x00004afd0b836e02, 0x000047d0e837cd82, + 0x00003b42405efeda, 0x00001531bafa4c95, 0x00007172cae34ac4, +}; +#else +uint32_t random_addresses[] = { + 0x8dc302e0, 0x929ab1e0, 0xb47683ba, 0xea519c73, 0xa19f1c90, 0xc49ba213, + 0x8f57c625, 0xadfe5137, 0x874d4d95, 0xaa20f09d, 0xcf21ebfc, 0xda7737f1, + 0xcedf392a, 0x83026c14, 0xccedca52, 0xc6ccf826, 0xe0cd9415, 0x997472ca, + 0xa21a44c1, 0xe82196f5, 0xa23fd66b, 0xc28d5590, 0xd009cdce, 0xcf0be646, + 0x8fc8c7ff, 0xe2a85984, 0xa3d3236b, 0x89a0619d, 0xc03db924, 0xb5d4cc1b, + 0xb96ee04c, 0xd191da48, 0xb432a000, 0xaa2bebbc, 0xa2fcb289, 0xb0cca89b, + 0xb0c18d6a, 0x88f58deb, 0xa4d42d1c, 0xe4d74e86, 0x99902b09, 0x8f786d31, + 0xbec5e381, 0x9a727e65, 0xa9a65040, 0xa880d789, 0x8f1b335e, 0xfc821c1e, + 0x97e34be4, 0xbbef84ed, 0xf447d197, 0xfd7ceee2, 0xe632348d, 0xee4590f4, + 0x958992a5, 0xd57e05d6, 0xfd240970, 0xc5b0dcff, 0xd96da2c2, 0xa7ae041d, }; +#endif // Only works on 64 bit #if __riscv_xlen == 64 -static inline void do_mmaps(struct addresses *mmap_addresses) -{ - /* - * Place all of the hint addresses on the boundaries of mmap - * sv39, sv48, sv57 - * User addresses end at 1<<38, 1<<47, 1<<56 respectively - */ - void *on_37_bits = (void *)(1UL << 37); - void *on_38_bits = (void *)(1UL << 38); - void *on_46_bits = (void *)(1UL << 46); - void *on_47_bits = (void *)(1UL << 47); - void *on_55_bits = (void *)(1UL << 55); - void *on_56_bits = (void *)(1UL << 56); +#define PROT (PROT_READ | PROT_WRITE) +#define FLAGS (MAP_PRIVATE | MAP_ANONYMOUS) - int prot = PROT_READ | PROT_WRITE; - int flags = MAP_PRIVATE | MAP_ANONYMOUS; +/* mmap must return a value that doesn't use more bits than the hint address. */ +static inline unsigned long get_max_value(unsigned long input) +{ + unsigned long max_bit = (1UL << (((sizeof(unsigned long) * 8) - 1 - + __builtin_clzl(input)))); - mmap_addresses->no_hint = - mmap(NULL, 5 * sizeof(int), prot, flags, 0, 0); - mmap_addresses->on_37_addr = - mmap(on_37_bits, 5 * sizeof(int), prot, flags, 0, 0); - mmap_addresses->on_38_addr = - mmap(on_38_bits, 5 * sizeof(int), prot, flags, 0, 0); - mmap_addresses->on_46_addr = - mmap(on_46_bits, 5 * sizeof(int), prot, flags, 0, 0); - mmap_addresses->on_47_addr = - mmap(on_47_bits, 5 * sizeof(int), prot, flags, 0, 0); - mmap_addresses->on_55_addr = - mmap(on_55_bits, 5 * sizeof(int), prot, flags, 0, 0); - mmap_addresses->on_56_addr = - mmap(on_56_bits, 5 * sizeof(int), prot, flags, 0, 0); + return max_bit + (max_bit - 1); } + +#define TEST_MMAPS \ + ({ \ + void *mmap_addr; \ + for (int i = 0; i < ARRAY_SIZE(random_addresses); i++) { \ + mmap_addr = mmap((void *)random_addresses[i], \ + 5 * sizeof(int), PROT, FLAGS, 0, 0); \ + EXPECT_NE(MAP_FAILED, mmap_addr); \ + EXPECT_GE((void *)get_max_value(random_addresses[i]), \ + mmap_addr); \ + mmap_addr = mmap((void *)random_addresses[i], \ + 5 * sizeof(int), PROT, FLAGS, 0, 0); \ + EXPECT_NE(MAP_FAILED, mmap_addr); \ + EXPECT_GE((void *)get_max_value(random_addresses[i]), \ + mmap_addr); \ + } \ + }) #endif /* __riscv_xlen == 64 */ static inline int memory_layout(void) { - int prot = PROT_READ | PROT_WRITE; - int flags = MAP_PRIVATE | MAP_ANONYMOUS; - - void *value1 = mmap(NULL, sizeof(int), prot, flags, 0, 0); - void *value2 = mmap(NULL, sizeof(int), prot, flags, 0, 0); + void *value1 = mmap(NULL, sizeof(int), PROT, FLAGS, 0, 0); + void *value2 = mmap(NULL, sizeof(int), PROT, FLAGS, 0, 0); return value2 > value1; } diff --git a/tools/testing/selftests/user_events/abi_test.c b/tools/testing/selftests/user_events/abi_test.c index cef1ff1af223..7288a05136ba 100644 --- a/tools/testing/selftests/user_events/abi_test.c +++ b/tools/testing/selftests/user_events/abi_test.c @@ -16,6 +16,8 @@ #include <sys/ioctl.h> #include <sys/stat.h> #include <unistd.h> +#include <glob.h> +#include <string.h> #include <asm/unistd.h> #include "../kselftest_harness.h" @@ -23,6 +25,62 @@ const char *data_file = "/sys/kernel/tracing/user_events_data"; const char *enable_file = "/sys/kernel/tracing/events/user_events/__abi_event/enable"; +const char *multi_dir_glob = "/sys/kernel/tracing/events/user_events_multi/__abi_event.*"; + +static int wait_for_delete(char *dir) +{ + struct stat buf; + int i; + + for (i = 0; i < 10000; ++i) { + if (stat(dir, &buf) == -1 && errno == ENOENT) + return 0; + + usleep(1000); + } + + return -1; +} + +static int find_multi_event_dir(char *unique_field, char *out_dir, int dir_len) +{ + char path[256]; + glob_t buf; + int i, ret; + + ret = glob(multi_dir_glob, GLOB_ONLYDIR, NULL, &buf); + + if (ret) + return -1; + + ret = -1; + + for (i = 0; i < buf.gl_pathc; ++i) { + FILE *fp; + + snprintf(path, sizeof(path), "%s/format", buf.gl_pathv[i]); + fp = fopen(path, "r"); + + if (!fp) + continue; + + while (fgets(path, sizeof(path), fp) != NULL) { + if (strstr(path, unique_field)) { + fclose(fp); + /* strscpy is not available, use snprintf */ + snprintf(out_dir, dir_len, "%s", buf.gl_pathv[i]); + ret = 0; + goto out; + } + } + + fclose(fp); + } +out: + globfree(&buf); + + return ret; +} static bool event_exists(void) { @@ -74,6 +132,39 @@ static int event_delete(void) return ret; } +static int reg_enable_multi(void *enable, int size, int bit, int flags, + char *args) +{ + struct user_reg reg = {0}; + char full_args[512] = {0}; + int fd = open(data_file, O_RDWR); + int len; + int ret; + + if (fd < 0) + return -1; + + len = snprintf(full_args, sizeof(full_args), "__abi_event %s", args); + + if (len > sizeof(full_args)) { + ret = -E2BIG; + goto out; + } + + reg.size = sizeof(reg); + reg.name_args = (__u64)full_args; + reg.flags = USER_EVENT_REG_MULTI_FORMAT | flags; + reg.enable_bit = bit; + reg.enable_addr = (__u64)enable; + reg.enable_size = size; + + ret = ioctl(fd, DIAG_IOCSREG, ®); +out: + close(fd); + + return ret; +} + static int reg_enable_flags(void *enable, int size, int bit, int flags) { struct user_reg reg = {0}; @@ -207,6 +298,49 @@ TEST_F(user, bit_sizes) { ASSERT_NE(0, reg_enable(&self->check, 128, 0)); } +TEST_F(user, multi_format) { + char first_dir[256]; + char second_dir[256]; + struct stat buf; + + /* Multiple formats for the same name should work */ + ASSERT_EQ(0, reg_enable_multi(&self->check, sizeof(int), 0, + 0, "u32 multi_first")); + + ASSERT_EQ(0, reg_enable_multi(&self->check, sizeof(int), 1, + 0, "u64 multi_second")); + + /* Same name with same format should also work */ + ASSERT_EQ(0, reg_enable_multi(&self->check, sizeof(int), 2, + 0, "u64 multi_second")); + + ASSERT_EQ(0, find_multi_event_dir("multi_first", + first_dir, sizeof(first_dir))); + + ASSERT_EQ(0, find_multi_event_dir("multi_second", + second_dir, sizeof(second_dir))); + + /* Should not be found in the same dir */ + ASSERT_NE(0, strcmp(first_dir, second_dir)); + + /* First dir should still exist */ + ASSERT_EQ(0, stat(first_dir, &buf)); + + /* Disabling first register should remove first dir */ + ASSERT_EQ(0, reg_disable(&self->check, 0)); + ASSERT_EQ(0, wait_for_delete(first_dir)); + + /* Second dir should still exist */ + ASSERT_EQ(0, stat(second_dir, &buf)); + + /* Disabling second register should remove second dir */ + ASSERT_EQ(0, reg_disable(&self->check, 1)); + /* Ensure bit 1 and 2 are tied together, should not delete yet */ + ASSERT_EQ(0, stat(second_dir, &buf)); + ASSERT_EQ(0, reg_disable(&self->check, 2)); + ASSERT_EQ(0, wait_for_delete(second_dir)); +} + TEST_F(user, forks) { int i; diff --git a/tools/testing/selftests/wireguard/qemu/arch/riscv32.config b/tools/testing/selftests/wireguard/qemu/arch/riscv32.config index 2fc36efb166d..a7f8e8a95625 100644 --- a/tools/testing/selftests/wireguard/qemu/arch/riscv32.config +++ b/tools/testing/selftests/wireguard/qemu/arch/riscv32.config @@ -3,6 +3,7 @@ CONFIG_ARCH_RV32I=y CONFIG_MMU=y CONFIG_FPU=y CONFIG_SOC_VIRT=y +CONFIG_RISCV_ISA_FALLBACK=y CONFIG_SERIAL_8250=y CONFIG_SERIAL_8250_CONSOLE=y CONFIG_SERIAL_OF_PLATFORM=y diff --git a/tools/testing/selftests/wireguard/qemu/arch/riscv64.config b/tools/testing/selftests/wireguard/qemu/arch/riscv64.config index dc266f3b1915..daeb3e5e0965 100644 --- a/tools/testing/selftests/wireguard/qemu/arch/riscv64.config +++ b/tools/testing/selftests/wireguard/qemu/arch/riscv64.config @@ -2,6 +2,7 @@ CONFIG_ARCH_RV64I=y CONFIG_MMU=y CONFIG_FPU=y CONFIG_SOC_VIRT=y +CONFIG_RISCV_ISA_FALLBACK=y CONFIG_SERIAL_8250=y CONFIG_SERIAL_8250_CONSOLE=y CONFIG_SERIAL_OF_PLATFORM=y |