Add a CXL unit test that exercises the replay_regions() helpers introduced in test/common.
The test creates regions through the user interface, captures the resulting region configuration, performs a cxl_acpi driver unbind/bind cycle, and verifies that the regions reconstructed during enumeration match the original configuration. This validates the decoder replay mechanism implemented in the kernel cxl_test module by replaying user-created regions as auto-discovered regions during driver initialization. Reviewed-by: Dave Jiang <[email protected]> Reviewed-by: "Fabio M. De Francesco" <[email protected]> Tested-by: "Fabio M. De Francesco" <[email protected]> Link: https://lore.kernel.org/r/7ec630ea29675b57c052e9606b1d33177e989a2a.1773466514.git.alison.schofi...@intel.com Signed-off-by: Alison Schofield <[email protected]> --- Changes in v2: - Rebase onto latest ndctl/pending - Add Fabio's Tags test/cxl-region-replay.sh | 148 ++++++++++++++++++++++++++++++++++++++ test/meson.build | 2 + 2 files changed, 150 insertions(+) create mode 100644 test/cxl-region-replay.sh diff --git a/test/cxl-region-replay.sh b/test/cxl-region-replay.sh new file mode 100644 index 000000000000..3049ca9f34b5 --- /dev/null +++ b/test/cxl-region-replay.sh @@ -0,0 +1,148 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2022 Intel Corporation. All rights reserved. + +. $(dirname $0)/common + +rc=77 + +set -ex + +trap 'err $LINENO' ERR + +check_prereq "jq" + +modprobe -r cxl_test +modprobe cxl_test + +# Replay support is exposed by cxl_acpi after cxl_test loads +if [ ! -e /sys/bus/platform/devices/cxl_acpi.0/decoder_reset_preserve_registry ]; then + do_skip "test requires decoder registry replay support" +fi + +rc=1 + +# Demonstrate and validate CXL region replay support in cxl_test. +# +# Replay helpers in test/common snapshot the current region topology, +# replay the configuration, and verify that the reconstructed regions +# match the original configuration. +# +# Tests should use the common helper: +# replay_regions +# +# This test serves as both a sanity check for replay support and an +# example of how other cxl_test unit tests can use replay_regions(). + +destroy_regions() { + $CXL destroy-region -f -b cxl_test all +} + +create_region() { + region=$($CXL create-region -d "$decoder" -m "$memdevs" | + jq -r ".region") + + if [[ ! $region ]]; then + echo "create-region failed for $decoder" + err "$LINENO" + fi +} + +create_x2_pmem_region() { + # Find a pmem-capable x2 decoder + decoder=$($CXL list -b cxl_test -D -d root | jq -r ".[] | + select(.pmem_capable == true) | + select(.nr_targets == 2) | + .decoder") + + # Select one memdev for each host-bridge interleave position + port_dev0=$($CXL list -T -d "$decoder" | jq -r ".[] | + .targets | .[] | select(.position == 0) | .target") + port_dev1=$($CXL list -T -d "$decoder" | jq -r ".[] | + .targets | .[] | select(.position == 1) | .target") + mem0=$($CXL list -M -p "$port_dev0" | jq -r ".[0].memdev") + mem1=$($CXL list -M -p "$port_dev1" | jq -r ".[0].memdev") + memdevs="$mem0 $mem1" + create_region +} + +create_x4_ram_region() { + # Find a volatile-capable x2 decoder + decoder=$($CXL list -b cxl_test -D -d root | jq -r ".[] | + select(.volatile_capable == true) | + select(.nr_targets == 2) | + .decoder") + + # Select two memdevs for each host-bridge interleave position + port_dev0=$($CXL list -T -d "$decoder" | jq -r ".[] | + .targets | .[] | select(.position == 0) | .target") + port_dev1=$($CXL list -T -d "$decoder" | jq -r ".[] | + .targets | .[] | select(.position == 1) | .target") + mem0=$($CXL list -M -p "$port_dev0" | jq -r ".[0].memdev") + mem1=$($CXL list -M -p "$port_dev1" | jq -r ".[0].memdev") + mem2=$($CXL list -M -p "$port_dev0" | jq -r ".[1].memdev") + mem3=$($CXL list -M -p "$port_dev1" | jq -r ".[1].memdev") + memdevs="$mem0 $mem1 $mem2 $mem3" + create_region +} + +AUTO_MEMDEVS="" +AUTO_ROOT_DECODER="" + +capture_auto_region() { + local region_json dec_json + + region_json=$($CXL list -R --targets) + + # Expect exactly one auto region + [ "$(jq 'length' <<<"$region_json")" -eq 1 ] || err "$LINENO" + + AUTO_MEMDEVS=$(jq -r '.[0].mappings | sort_by(.position) | .[].memdev' \ + <<<"$region_json" | xargs) + [[ $AUTO_MEMDEVS ]] || err "$LINENO" + + dec_json=$($CXL list -R --decoders) + AUTO_ROOT_DECODER=$(jq -r '.[0]["root decoders"][0].decoder' <<<"$dec_json") + [[ $AUTO_ROOT_DECODER ]] || err "$LINENO" +} + +create_user_region_in_auto_region_space() { + decoder="$AUTO_ROOT_DECODER" + memdevs="$AUTO_MEMDEVS" + create_region +} + +# To remove the auto region, destroy and recreate in user space. +# With that action, there will be no 'auto' decoders and it will not be +# preserved across acpi rebind. +# +# This is done here as example if test wants the resources freed +remove_auto_region() { + capture_auto_region + destroy_regions + create_user_region_in_auto_region_space + destroy_regions + replay_regions || err "$LINENO" +} + +# Replay the built-in auto region +[ "$($CXL list -R | jq 'length')" -ne 0 ] || err "$LINENO" +replay_regions || err "$LINENO" + +# Remove the built-in auto region to free up resources +remove_auto_region +[ "$($CXL list -R | jq 'length')" -eq 0 ] || err "$LINENO" + +# Create and replay a volatile region +create_x4_ram_region +replay_regions || err "$LINENO" + +# Add-on a pmem region +create_x2_pmem_region + +# Replay both the x4_ram and x2_pmem +replay_regions || err "$LINENO" + +check_dmesg "$LINENO" + +modprobe -r cxl_test diff --git a/test/meson.build b/test/meson.build index 4260a3fa4448..e0e2193bfd51 100644 --- a/test/meson.build +++ b/test/meson.build @@ -170,6 +170,7 @@ cxl_qos_class = find_program('cxl-qos-class.sh') cxl_translate = find_program('cxl-translate.sh') cxl_elc = find_program('cxl-elc.sh') cxl_dax_hmem = find_program('cxl-dax-hmem.sh') +cxl_region_replay = find_program('cxl-region-replay.sh') tests = [ [ 'libndctl', libndctl, 'ndctl' ], @@ -205,6 +206,7 @@ tests = [ [ 'cxl-translate.sh', cxl_translate, 'cxl' ], [ 'cxl-elc.sh', cxl_elc, 'cxl' ], [ 'cxl-dax-hmem.sh', cxl_dax_hmem, 'cxl' ], + [ 'cxl-region-replay.sh', cxl_region_replay, 'cxl' ], ] if get_option('destructive').enabled() -- 2.37.3
