pci-sim: Add local validation tooling

The pci-sim module is developed out of tree, but it needs to keep
following kernel coding conventions as it grows. Developers currently have
to know which kernel tools to run and which warnings are expected for this
module.

Add local validation support for pci-sim. This includes a kernel
clang-format baseline, a vendored checkpatch copy with a pci-sim-specific
--no-spelling option, and lint and build-test Makefile targets. Spelling
remains owned by the repository pre-commit codespell hook.

Normalize the existing pci-sim C sources with the kernel clang-format
configuration and clean up the current checkpatch baseline where practical.
The remaining ignored checkpatch types are limited to clang-format line
wrapping, the isolated out-of-tree compatibility header, and the Makefile
path list used by the lint target.

Document the expected developer workflow so future pci-sim changes can be
checked consistently.

Assisted-By: pi gpt-5.5
Change-Id: Ic4183133157000bf5bc32e08cc78cc7e3377a648
Signed-off-by: Sean Mooney <work@seanmooney.info>
This commit is contained in:
Sean Mooney committed 2026-07-09 12:33:32 +01:00
1 parent 9b6efd4168
commit 3f9aa074b4
14 files changed
+9275 -239

No files matched your search

+1
View File
@@ -45,6 +45,7 @@ repos:
hooks:
- id: codespell
args: ['--ignore-words=doc/dictionary.txt']
exclude: ^pci-sim/tools/checkpatch\.pl$
- repo: https://github.com/sphinx-contrib/sphinx-lint
rev: v1.0.0
hooks:
+805
View File
@@ -0,0 +1,805 @@
# SPDX-License-Identifier: GPL-2.0
#
# clang-format configuration file. Intended for clang-format >= 11.
#
# For more information, see:
#
# Documentation/dev-tools/clang-format.rst
# https://clang.llvm.org/docs/ClangFormat.html
# https://clang.llvm.org/docs/ClangFormatStyleOptions.html
#
---
AccessModifierOffset: -4
AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
AlignEscapedNewlines: Left
AlignOperands: true
AlignTrailingComments: false
AllowAllParametersOfDeclarationOnNextLine: false
AllowShortBlocksOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: None
AllowShortIfStatementsOnASingleLine: false
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: false
BinPackArguments: true
BinPackParameters: true
BraceWrapping:
AfterClass: false
AfterControlStatement: false
AfterEnum: false
AfterFunction: true
AfterNamespace: true
AfterObjCDeclaration: false
AfterStruct: false
AfterUnion: false
AfterExternBlock: false
BeforeCatch: false
BeforeElse: false
IndentBraces: false
SplitEmptyFunction: true
SplitEmptyRecord: true
SplitEmptyNamespace: true
BreakBeforeBinaryOperators: None
BreakBeforeBraces: Custom
BreakBeforeInheritanceComma: false
BreakBeforeTernaryOperators: false
BreakConstructorInitializersBeforeComma: false
BreakConstructorInitializers: BeforeComma
BreakAfterJavaFieldAnnotations: false
BreakStringLiterals: false
ColumnLimit: 80
CommentPragmas: '^ IWYU pragma:'
CompactNamespaces: false
ConstructorInitializerAllOnOneLineOrOnePerLine: false
ConstructorInitializerIndentWidth: 8
ContinuationIndentWidth: 8
Cpp11BracedListStyle: false
DerivePointerAlignment: false
DisableFormat: false
ExperimentalAutoDetectBinPacking: false
FixNamespaceComments: false
# Taken from:
# git grep -h '^#define [^[:space:]]*for_each[^[:space:]]*(' include/ tools/ \
# | sed "s,^#define \([^[:space:]]*for_each[^[:space:]]*\)(.*$, - '\1'," \
# | LC_ALL=C sort -u
ForEachMacros:
- '__ata_qc_for_each'
- '__bio_for_each_bvec'
- '__bio_for_each_segment'
- '__evlist__for_each_entry'
- '__evlist__for_each_entry_continue'
- '__evlist__for_each_entry_from'
- '__evlist__for_each_entry_reverse'
- '__evlist__for_each_entry_safe'
- '__for_each_mem_range'
- '__for_each_mem_range_rev'
- '__for_each_thread'
- '__hlist_for_each_rcu'
- '__map__for_each_symbol_by_name'
- '__pci_bus_for_each_res0'
- '__pci_bus_for_each_res1'
- '__pci_dev_for_each_res0'
- '__pci_dev_for_each_res1'
- '__perf_evlist__for_each_entry'
- '__perf_evlist__for_each_entry_reverse'
- '__perf_evlist__for_each_entry_safe'
- '__rq_for_each_bio'
- '__shost_for_each_device'
- '__sym_for_each'
- '_for_each_counter'
- 'apei_estatus_for_each_section'
- 'ata_for_each_dev'
- 'ata_for_each_link'
- 'ata_qc_for_each'
- 'ata_qc_for_each_raw'
- 'ata_qc_for_each_with_internal'
- 'ax25_for_each'
- 'ax25_uid_for_each'
- 'bio_for_each_bvec'
- 'bio_for_each_bvec_all'
- 'bio_for_each_folio_all'
- 'bio_for_each_integrity_vec'
- 'bio_for_each_segment'
- 'bio_for_each_segment_all'
- 'bio_list_for_each'
- 'bip_for_each_vec'
- 'bond_for_each_slave'
- 'bond_for_each_slave_rcu'
- 'bpf_for_each'
- 'bpf_for_each_reg_in_vstate'
- 'bpf_for_each_reg_in_vstate_mask'
- 'bpf_for_each_spilled_reg'
- 'bpf_object__for_each_map'
- 'bpf_object__for_each_program'
- 'btree_for_each_safe128'
- 'btree_for_each_safe32'
- 'btree_for_each_safe64'
- 'btree_for_each_safel'
- 'card_for_each_dev'
- 'cgroup_taskset_for_each'
- 'cgroup_taskset_for_each_leader'
- 'cpu_aggr_map__for_each_idx'
- 'cpufreq_for_each_efficient_entry_idx'
- 'cpufreq_for_each_entry'
- 'cpufreq_for_each_entry_idx'
- 'cpufreq_for_each_valid_entry'
- 'cpufreq_for_each_valid_entry_idx'
- 'css_for_each_child'
- 'css_for_each_descendant_post'
- 'css_for_each_descendant_pre'
- 'damon_for_each_region'
- 'damon_for_each_region_from'
- 'damon_for_each_region_safe'
- 'damon_for_each_scheme'
- 'damon_for_each_scheme_safe'
- 'damon_for_each_target'
- 'damon_for_each_target_safe'
- 'damos_for_each_core_filter'
- 'damos_for_each_core_filter_safe'
- 'damos_for_each_ops_filter'
- 'damos_for_each_ops_filter_safe'
- 'damos_for_each_quota_goal'
- 'damos_for_each_quota_goal_safe'
- 'data__for_each_file'
- 'data__for_each_file_new'
- 'data__for_each_file_start'
- 'def_for_each_cpu'
- 'device_for_each_child_node'
- 'device_for_each_child_node_scoped'
- 'dma_fence_array_for_each'
- 'dma_fence_chain_for_each'
- 'dma_fence_unwrap_for_each'
- 'dma_resv_for_each_fence'
- 'dma_resv_for_each_fence_unlocked'
- 'do_for_each_ftrace_op'
- 'drm_atomic_crtc_for_each_plane'
- 'drm_atomic_crtc_state_for_each_plane'
- 'drm_atomic_crtc_state_for_each_plane_state'
- 'drm_atomic_for_each_plane_damage'
- 'drm_client_for_each_connector_iter'
- 'drm_client_for_each_modeset'
- 'drm_connector_for_each_possible_encoder'
- 'drm_exec_for_each_locked_object'
- 'drm_exec_for_each_locked_object_reverse'
- 'drm_for_each_bridge_in_chain_scoped'
- 'drm_for_each_connector_iter'
- 'drm_for_each_crtc'
- 'drm_for_each_crtc_reverse'
- 'drm_for_each_encoder'
- 'drm_for_each_encoder_mask'
- 'drm_for_each_fb'
- 'drm_for_each_legacy_plane'
- 'drm_for_each_plane'
- 'drm_for_each_plane_mask'
- 'drm_for_each_privobj'
- 'drm_gem_for_each_gpuvm_bo'
- 'drm_gem_for_each_gpuvm_bo_safe'
- 'drm_gpusvm_for_each_range'
- 'drm_gpuva_for_each_op'
- 'drm_gpuva_for_each_op_from_reverse'
- 'drm_gpuva_for_each_op_reverse'
- 'drm_gpuva_for_each_op_safe'
- 'drm_gpuvm_bo_for_each_va'
- 'drm_gpuvm_bo_for_each_va_safe'
- 'drm_gpuvm_for_each_va'
- 'drm_gpuvm_for_each_va_range'
- 'drm_gpuvm_for_each_va_range_safe'
- 'drm_gpuvm_for_each_va_safe'
- 'drm_mm_for_each_hole'
- 'drm_mm_for_each_node'
- 'drm_mm_for_each_node_in_range'
- 'drm_mm_for_each_node_safe'
- 'dsa_switch_for_each_available_port'
- 'dsa_switch_for_each_cpu_port'
- 'dsa_switch_for_each_cpu_port_continue_reverse'
- 'dsa_switch_for_each_port'
- 'dsa_switch_for_each_port_continue_reverse'
- 'dsa_switch_for_each_port_safe'
- 'dsa_switch_for_each_user_port'
- 'dsa_switch_for_each_user_port_continue_reverse'
- 'dsa_tree_for_each_cpu_port'
- 'dsa_tree_for_each_user_port'
- 'dsa_tree_for_each_user_port_continue_reverse'
- 'dso__for_each_symbol'
- 'elf_hash_for_each_possible'
- 'elf_symtab__for_each_symbol'
- 'evlist__for_each_cpu'
- 'evlist__for_each_entry'
- 'evlist__for_each_entry_continue'
- 'evlist__for_each_entry_from'
- 'evlist__for_each_entry_reverse'
- 'evlist__for_each_entry_safe'
- 'flow_action_for_each'
- 'for_each_acpi_consumer_dev'
- 'for_each_acpi_dev_match'
- 'for_each_active_dev_scope'
- 'for_each_active_drhd_unit'
- 'for_each_active_iommu'
- 'for_each_active_irq'
- 'for_each_active_route'
- 'for_each_aggr_pgid'
- 'for_each_alloc_capable_rdt_resource'
- 'for_each_and_bit'
- 'for_each_andnot_bit'
- 'for_each_available_child_of_node'
- 'for_each_available_child_of_node_scoped'
- 'for_each_bench'
- 'for_each_bio'
- 'for_each_board_func_rsrc'
- 'for_each_btf_ext_rec'
- 'for_each_btf_ext_sec'
- 'for_each_bvec'
- 'for_each_capable_rdt_resource'
- 'for_each_card_auxs'
- 'for_each_card_auxs_safe'
- 'for_each_card_components'
- 'for_each_card_dapms'
- 'for_each_card_pre_auxs'
- 'for_each_card_prelinks'
- 'for_each_card_rtds'
- 'for_each_card_rtds_safe'
- 'for_each_card_widgets'
- 'for_each_card_widgets_safe'
- 'for_each_cgroup_storage_type'
- 'for_each_child_of_node'
- 'for_each_child_of_node_scoped'
- 'for_each_child_of_node_with_prefix'
- 'for_each_clear_bit'
- 'for_each_clear_bit_from'
- 'for_each_clear_bitrange'
- 'for_each_clear_bitrange_from'
- 'for_each_cmd'
- 'for_each_cmsghdr'
- 'for_each_collection'
- 'for_each_comp_order'
- 'for_each_compatible_node'
- 'for_each_component_dais'
- 'for_each_component_dais_safe'
- 'for_each_conduit'
- 'for_each_console'
- 'for_each_console_srcu'
- 'for_each_cpu'
- 'for_each_cpu_and'
- 'for_each_cpu_andnot'
- 'for_each_cpu_from'
- 'for_each_cpu_or'
- 'for_each_cpu_wrap'
- 'for_each_dapm_widgets'
- 'for_each_dedup_cand'
- 'for_each_dev_addr'
- 'for_each_dev_scope'
- 'for_each_dma_cap_mask'
- 'for_each_dpcm_be'
- 'for_each_dpcm_be_rollback'
- 'for_each_dpcm_be_safe'
- 'for_each_dpcm_fe'
- 'for_each_drhd_unit'
- 'for_each_dss_dev'
- 'for_each_efi_memory_desc'
- 'for_each_efi_memory_desc_in_map'
- 'for_each_element'
- 'for_each_element_extid'
- 'for_each_element_id'
- 'for_each_enabled_cpu'
- 'for_each_endpoint_of_node'
- 'for_each_event'
- 'for_each_event_tps'
- 'for_each_evictable_lru'
- 'for_each_fib6_node_rt_rcu'
- 'for_each_fib6_walker_rt'
- 'for_each_file_lock'
- 'for_each_free_mem_range'
- 'for_each_free_mem_range_reverse'
- 'for_each_func_rsrc'
- 'for_each_gpiochip_node'
- 'for_each_group_evsel'
- 'for_each_group_evsel_head'
- 'for_each_group_member'
- 'for_each_group_member_head'
- 'for_each_hstate'
- 'for_each_hwgpio'
- 'for_each_hwgpio_in_range'
- 'for_each_if'
- 'for_each_inject_fn'
- 'for_each_insn'
- 'for_each_insn_op_loc'
- 'for_each_insn_prefix'
- 'for_each_intid'
- 'for_each_iommu'
- 'for_each_ip_tunnel_rcu'
- 'for_each_irq_desc'
- 'for_each_irq_nr'
- 'for_each_lang'
- 'for_each_link_ch_maps'
- 'for_each_link_codecs'
- 'for_each_link_cpus'
- 'for_each_link_platforms'
- 'for_each_lru'
- 'for_each_matching_node'
- 'for_each_matching_node_and_match'
- 'for_each_media_entity_data_link'
- 'for_each_mem_pfn_range'
- 'for_each_mem_range'
- 'for_each_mem_range_rev'
- 'for_each_mem_region'
- 'for_each_member'
- 'for_each_memory'
- 'for_each_migratetype_order'
- 'for_each_missing_reg'
- 'for_each_mle_subelement'
- 'for_each_mod_mem_type'
- 'for_each_mon_capable_rdt_resource'
- 'for_each_mp_bvec'
- 'for_each_net'
- 'for_each_net_continue_reverse'
- 'for_each_net_rcu'
- 'for_each_netdev'
- 'for_each_netdev_continue'
- 'for_each_netdev_continue_rcu'
- 'for_each_netdev_continue_reverse'
- 'for_each_netdev_dump'
- 'for_each_netdev_feature'
- 'for_each_netdev_in_bond_rcu'
- 'for_each_netdev_rcu'
- 'for_each_netdev_reverse'
- 'for_each_netdev_safe'
- 'for_each_new_connector_in_state'
- 'for_each_new_crtc_in_state'
- 'for_each_new_mst_mgr_in_state'
- 'for_each_new_plane_in_state'
- 'for_each_new_plane_in_state_reverse'
- 'for_each_new_private_obj_in_state'
- 'for_each_new_reg'
- 'for_each_nhlt_endpoint'
- 'for_each_nhlt_endpoint_fmtcfg'
- 'for_each_nhlt_fmtcfg'
- 'for_each_node'
- 'for_each_node_by_name'
- 'for_each_node_by_type'
- 'for_each_node_mask'
- 'for_each_node_numadist'
- 'for_each_node_state'
- 'for_each_node_with_cpus'
- 'for_each_node_with_property'
- 'for_each_nonreserved_multicast_dest_pgid'
- 'for_each_numa_hop_mask'
- 'for_each_of_allnodes'
- 'for_each_of_allnodes_from'
- 'for_each_of_cpu_node'
- 'for_each_of_graph_port'
- 'for_each_of_graph_port_endpoint'
- 'for_each_of_pci_range'
- 'for_each_old_connector_in_state'
- 'for_each_old_crtc_in_state'
- 'for_each_old_mst_mgr_in_state'
- 'for_each_old_plane_in_state'
- 'for_each_old_private_obj_in_state'
- 'for_each_oldnew_connector_in_state'
- 'for_each_oldnew_crtc_in_state'
- 'for_each_oldnew_mst_mgr_in_state'
- 'for_each_oldnew_plane_in_state'
- 'for_each_oldnew_plane_in_state_reverse'
- 'for_each_oldnew_private_obj_in_state'
- 'for_each_online_cpu'
- 'for_each_online_cpu_wrap'
- 'for_each_online_node'
- 'for_each_online_pgdat'
- 'for_each_or_bit'
- 'for_each_page_ext'
- 'for_each_path'
- 'for_each_pci_bridge'
- 'for_each_pci_dev'
- 'for_each_pcm_streams'
- 'for_each_physmem_range'
- 'for_each_populated_zone'
- 'for_each_possible_cpu'
- 'for_each_possible_cpu_wrap'
- 'for_each_present_blessed_reg'
- 'for_each_present_cpu'
- 'for_each_present_section_nr'
- 'for_each_prime_number'
- 'for_each_prime_number_from'
- 'for_each_probe_cache_entry'
- 'for_each_process'
- 'for_each_process_thread'
- 'for_each_prop_codec_conf'
- 'for_each_prop_dai_codec'
- 'for_each_prop_dai_cpu'
- 'for_each_prop_dlc_codecs'
- 'for_each_prop_dlc_cpus'
- 'for_each_prop_dlc_platforms'
- 'for_each_property_of_node'
- 'for_each_pt_level_entry'
- 'for_each_rdt_resource'
- 'for_each_reg'
- 'for_each_reg_filtered'
- 'for_each_reloc'
- 'for_each_reloc_from'
- 'for_each_requested_gpio'
- 'for_each_requested_gpio_in_range'
- 'for_each_reserved_child_of_node'
- 'for_each_reserved_mem_range'
- 'for_each_reserved_mem_region'
- 'for_each_rtd_ch_maps'
- 'for_each_rtd_codec_dais'
- 'for_each_rtd_components'
- 'for_each_rtd_cpu_dais'
- 'for_each_rtd_dais'
- 'for_each_rtd_dais_reverse'
- 'for_each_sband_iftype_data'
- 'for_each_script'
- 'for_each_sec'
- 'for_each_set_bit'
- 'for_each_set_bit_from'
- 'for_each_set_bit_wrap'
- 'for_each_set_bitrange'
- 'for_each_set_bitrange_from'
- 'for_each_set_clump8'
- 'for_each_sg'
- 'for_each_sg_dma_page'
- 'for_each_sg_page'
- 'for_each_sgtable_dma_page'
- 'for_each_sgtable_dma_sg'
- 'for_each_sgtable_page'
- 'for_each_sgtable_sg'
- 'for_each_sibling_event'
- 'for_each_sta_active_link'
- 'for_each_subelement'
- 'for_each_subelement_extid'
- 'for_each_subelement_id'
- 'for_each_sublist'
- 'for_each_subsystem'
- 'for_each_suite'
- 'for_each_supported_activate_fn'
- 'for_each_supported_inject_fn'
- 'for_each_sym'
- 'for_each_thread'
- 'for_each_token'
- 'for_each_unicast_dest_pgid'
- 'for_each_valid_link'
- 'for_each_vif_active_link'
- 'for_each_vma'
- 'for_each_vma_range'
- 'for_each_vsi'
- 'for_each_wakeup_source'
- 'for_each_zone'
- 'for_each_zone_zonelist'
- 'for_each_zone_zonelist_nodemask'
- 'func_for_each_insn'
- 'fwnode_for_each_available_child_node'
- 'fwnode_for_each_child_node'
- 'fwnode_for_each_parent_node'
- 'fwnode_graph_for_each_endpoint'
- 'gadget_for_each_ep'
- 'genradix_for_each'
- 'genradix_for_each_from'
- 'genradix_for_each_reverse'
- 'hash_for_each'
- 'hash_for_each_possible'
- 'hash_for_each_possible_rcu'
- 'hash_for_each_possible_rcu_notrace'
- 'hash_for_each_possible_safe'
- 'hash_for_each_rcu'
- 'hash_for_each_safe'
- 'hashmap__for_each_entry'
- 'hashmap__for_each_entry_safe'
- 'hashmap__for_each_key_entry'
- 'hashmap__for_each_key_entry_safe'
- 'hctx_for_each_ctx'
- 'hists__for_each_format'
- 'hists__for_each_sort_list'
- 'hlist_bl_for_each_entry'
- 'hlist_bl_for_each_entry_rcu'
- 'hlist_bl_for_each_entry_safe'
- 'hlist_for_each'
- 'hlist_for_each_entry'
- 'hlist_for_each_entry_continue'
- 'hlist_for_each_entry_continue_rcu'
- 'hlist_for_each_entry_continue_rcu_bh'
- 'hlist_for_each_entry_from'
- 'hlist_for_each_entry_from_rcu'
- 'hlist_for_each_entry_rcu'
- 'hlist_for_each_entry_rcu_bh'
- 'hlist_for_each_entry_rcu_notrace'
- 'hlist_for_each_entry_safe'
- 'hlist_for_each_entry_srcu'
- 'hlist_for_each_safe'
- 'hlist_nulls_for_each_entry'
- 'hlist_nulls_for_each_entry_from'
- 'hlist_nulls_for_each_entry_rcu'
- 'hlist_nulls_for_each_entry_safe'
- 'i3c_bus_for_each_i2cdev'
- 'i3c_bus_for_each_i3cdev'
- 'idr_for_each_entry'
- 'idr_for_each_entry_continue'
- 'idr_for_each_entry_continue_ul'
- 'idr_for_each_entry_ul'
- 'iio_for_each_active_channel'
- 'in_dev_for_each_ifa_rcu'
- 'in_dev_for_each_ifa_rtnl'
- 'in_dev_for_each_ifa_rtnl_net'
- 'inet_bind_bucket_for_each'
- 'interval_tree_for_each_span'
- 'intlist__for_each_entry'
- 'intlist__for_each_entry_safe'
- 'kcore_copy__for_each_phdr'
- 'key_for_each'
- 'key_for_each_safe'
- 'klp_for_each_func'
- 'klp_for_each_func_safe'
- 'klp_for_each_func_static'
- 'klp_for_each_object'
- 'klp_for_each_object_safe'
- 'klp_for_each_object_static'
- 'kunit_suite_for_each_test_case'
- 'kvm_for_each_memslot'
- 'kvm_for_each_memslot_in_gfn_range'
- 'kvm_for_each_vcpu'
- 'libbpf_nla_for_each_attr'
- 'list_for_each'
- 'list_for_each_codec'
- 'list_for_each_codec_safe'
- 'list_for_each_continue'
- 'list_for_each_entry'
- 'list_for_each_entry_continue'
- 'list_for_each_entry_continue_rcu'
- 'list_for_each_entry_continue_reverse'
- 'list_for_each_entry_from'
- 'list_for_each_entry_from_rcu'
- 'list_for_each_entry_from_reverse'
- 'list_for_each_entry_lockless'
- 'list_for_each_entry_rcu'
- 'list_for_each_entry_reverse'
- 'list_for_each_entry_safe'
- 'list_for_each_entry_safe_continue'
- 'list_for_each_entry_safe_from'
- 'list_for_each_entry_safe_reverse'
- 'list_for_each_entry_srcu'
- 'list_for_each_from'
- 'list_for_each_prev'
- 'list_for_each_prev_safe'
- 'list_for_each_rcu'
- 'list_for_each_safe'
- 'llist_for_each'
- 'llist_for_each_entry'
- 'llist_for_each_entry_safe'
- 'llist_for_each_safe'
- 'lwq_for_each_safe'
- 'map__for_each_symbol'
- 'map__for_each_symbol_by_name'
- 'mas_for_each'
- 'mas_for_each_rev'
- 'mci_for_each_dimm'
- 'media_device_for_each_entity'
- 'media_device_for_each_intf'
- 'media_device_for_each_link'
- 'media_device_for_each_pad'
- 'media_entity_for_each_pad'
- 'media_pipeline_for_each_entity'
- 'media_pipeline_for_each_pad'
- 'mlx5_lag_for_each_peer_mdev'
- 'mptcp_for_each_subflow'
- 'msi_domain_for_each_desc'
- 'msi_for_each_desc'
- 'mt_for_each'
- 'nanddev_io_for_each_block'
- 'nanddev_io_for_each_page'
- 'neigh_for_each_in_bucket'
- 'neigh_for_each_in_bucket_rcu'
- 'neigh_for_each_in_bucket_safe'
- 'netdev_for_each_lower_dev'
- 'netdev_for_each_lower_private'
- 'netdev_for_each_lower_private_rcu'
- 'netdev_for_each_mc_addr'
- 'netdev_for_each_synced_mc_addr'
- 'netdev_for_each_synced_uc_addr'
- 'netdev_for_each_uc_addr'
- 'netdev_for_each_upper_dev_rcu'
- 'netdev_hw_addr_list_for_each'
- 'nft_rule_for_each_expr'
- 'nla_for_each_attr'
- 'nla_for_each_attr_type'
- 'nla_for_each_nested'
- 'nla_for_each_nested_type'
- 'nlmsg_for_each_attr'
- 'nlmsg_for_each_msg'
- 'nr_neigh_for_each'
- 'nr_neigh_for_each_safe'
- 'nr_node_for_each'
- 'nr_node_for_each_safe'
- 'of_for_each_phandle'
- 'of_property_for_each_string'
- 'of_property_for_each_u32'
- 'pci_bus_for_each_resource'
- 'pci_dev_for_each_resource'
- 'pcl_for_each_chunk'
- 'pcl_for_each_segment'
- 'pcm_for_each_format'
- 'perf_config_items__for_each_entry'
- 'perf_config_sections__for_each_entry'
- 'perf_config_set__for_each_entry'
- 'perf_cpu_map__for_each_cpu'
- 'perf_cpu_map__for_each_cpu_skip_any'
- 'perf_cpu_map__for_each_idx'
- 'perf_evlist__for_each_entry'
- 'perf_evlist__for_each_entry_reverse'
- 'perf_evlist__for_each_entry_safe'
- 'perf_evlist__for_each_evsel'
- 'perf_evlist__for_each_mmap'
- 'perf_evsel_for_each_per_thread_period_safe'
- 'perf_hpp_list__for_each_format'
- 'perf_hpp_list__for_each_format_safe'
- 'perf_hpp_list__for_each_sort_list'
- 'perf_hpp_list__for_each_sort_list_safe'
- 'plist_for_each'
- 'plist_for_each_continue'
- 'plist_for_each_entry'
- 'plist_for_each_entry_continue'
- 'plist_for_each_entry_safe'
- 'plist_for_each_safe'
- 'pnp_for_each_card'
- 'pnp_for_each_dev'
- 'protocol_for_each_card'
- 'protocol_for_each_dev'
- 'queue_for_each_hw_ctx'
- 'radix_tree_for_each_slot'
- 'radix_tree_for_each_tagged'
- 'rb_for_each'
- 'rbtree_postorder_for_each_entry_safe'
- 'rdma_for_each_block'
- 'rdma_for_each_port'
- 'rdma_umem_for_each_dma_block'
- 'resource_list_for_each_entry'
- 'resource_list_for_each_entry_safe'
- 'rhl_for_each_entry_rcu'
- 'rhl_for_each_rcu'
- 'rht_for_each'
- 'rht_for_each_entry'
- 'rht_for_each_entry_from'
- 'rht_for_each_entry_rcu'
- 'rht_for_each_entry_rcu_from'
- 'rht_for_each_entry_safe'
- 'rht_for_each_from'
- 'rht_for_each_rcu'
- 'rht_for_each_rcu_from'
- 'rq_for_each_bvec'
- 'rq_for_each_segment'
- 'rq_list_for_each'
- 'rq_list_for_each_safe'
- 'sample_read_group__for_each'
- 'scsi_for_each_prot_sg'
- 'scsi_for_each_sg'
- 'sctp_for_each_hentry'
- 'sctp_skb_for_each'
- 'sec_for_each_insn'
- 'sec_for_each_insn_continue'
- 'sec_for_each_insn_from'
- 'sec_for_each_sym'
- 'shdma_for_each_chan'
- 'shost_for_each_device'
- 'sk_for_each'
- 'sk_for_each_bound'
- 'sk_for_each_bound_safe'
- 'sk_for_each_entry_offset_rcu'
- 'sk_for_each_from'
- 'sk_for_each_rcu'
- 'sk_for_each_safe'
- 'sk_nulls_for_each'
- 'sk_nulls_for_each_from'
- 'sk_nulls_for_each_rcu'
- 'snd_array_for_each'
- 'snd_pcm_group_for_each_entry'
- 'snd_soc_dapm_widget_for_each_path'
- 'snd_soc_dapm_widget_for_each_path_safe'
- 'snd_soc_dapm_widget_for_each_sink_path'
- 'snd_soc_dapm_widget_for_each_source_path'
- 'sparsebit_for_each_set_range'
- 'strlist__for_each_entry'
- 'strlist__for_each_entry_safe'
- 'sym_for_each_insn'
- 'sym_for_each_insn_continue_reverse'
- 'symbols__for_each_entry'
- 'tb_property_for_each'
- 'tcf_act_for_each_action'
- 'tcf_exts_for_each_action'
- 'test_suite__for_each_test_case'
- 'tool_pmu__for_each_event'
- 'ttm_bo_lru_for_each_reserved_guarded'
- 'ttm_resource_manager_for_each_res'
- 'udp_lrpa_for_each_entry_rcu'
- 'udp_portaddr_for_each_entry'
- 'udp_portaddr_for_each_entry_rcu'
- 'usb_hub_for_each_child'
- 'v4l2_device_for_each_subdev'
- 'v4l2_m2m_for_each_dst_buf'
- 'v4l2_m2m_for_each_dst_buf_safe'
- 'v4l2_m2m_for_each_src_buf'
- 'v4l2_m2m_for_each_src_buf_safe'
- 'virtio_device_for_each_vq'
- 'vkms_config_for_each_connector'
- 'vkms_config_for_each_crtc'
- 'vkms_config_for_each_encoder'
- 'vkms_config_for_each_plane'
- 'vkms_config_connector_for_each_possible_encoder'
- 'vkms_config_encoder_for_each_possible_crtc'
- 'vkms_config_plane_for_each_possible_crtc'
- 'while_for_each_ftrace_op'
- 'workloads__for_each'
- 'xa_for_each'
- 'xa_for_each_marked'
- 'xa_for_each_range'
- 'xa_for_each_start'
- 'xas_for_each'
- 'xas_for_each_conflict'
- 'xas_for_each_marked'
- 'xbc_array_for_each_value'
- 'xbc_for_each_key_value'
- 'xbc_node_for_each_array_value'
- 'xbc_node_for_each_child'
- 'xbc_node_for_each_key_value'
- 'xbc_node_for_each_subkey'
- 'ynl_attr_for_each'
- 'ynl_attr_for_each_nested'
- 'ynl_attr_for_each_payload'
- 'zorro_for_each_dev'
- 'zpci_bus_for_each'
IncludeBlocks: Preserve
IncludeCategories:
- Regex: '.*'
Priority: 1
IncludeIsMainRegex: '(Test)?$'
IndentCaseLabels: false
IndentGotoLabels: false
IndentPPDirectives: None
IndentWidth: 8
IndentWrappedFunctionNames: false
JavaScriptQuotes: Leave
JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: false
MacroBlockBegin: ''
MacroBlockEnd: ''
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
ObjCBinPackProtocolList: Auto
ObjCBlockIndentWidth: 8
ObjCSpaceAfterProperty: true
ObjCSpaceBeforeProtocolList: true
# Taken from git's rules
PenaltyBreakAssignment: 10
PenaltyBreakBeforeFirstCallParameter: 100000
PenaltyBreakComment: 10
PenaltyBreakFirstLessLess: 0
PenaltyBreakString: 10
PenaltyExcessCharacter: 100
PenaltyReturnTypeOnItsOwnLine: 60
PointerAlignment: Right
ReflowComments: false
SortIncludes: false
SortUsingDeclarations: false
SpaceAfterCStyleCast: false
SpaceAfterTemplateKeyword: true
SpaceBeforeAssignmentOperators: true
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
SpaceBeforeParens: ControlStatementsExceptForEachMacros
SpaceBeforeRangeBasedForLoopColon: true
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1
SpacesInAngles: false
SpacesInContainerLiterals: false
SpacesInCStyleCastParentheses: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
Standard: Cpp03
TabWidth: 8
UseTab: Always
...
+47 -4
View File
@@ -10,9 +10,15 @@ fake_pci_sriov-y := \
KDIR ?= /lib/modules/$(shell uname -r)/build
PWD := $(CURDIR)
PERL ?= perl
LINT_BASE ?= origin/master
.PHONY: all modules clean install modules_install check-kernel-config \
test test-loopback test-multi-pf
PCI_SIM_FORMAT_FILES := $(wildcard $(PWD)/*.c) $(wildcard $(PWD)/*.h)
PCI_SIM_CHECKPATCH_PATHS := *.c *.h Kconfig Makefile *.rst
.PHONY: all modules clean install modules_install check check-kernel-config \
lint lint-checkpatch lint-format lint-build-warnings test test-build \
test-host test-loopback test-multi-pf
all: modules
@@ -29,9 +35,46 @@ install modules_install:
check-kernel-config:
../tools/check-kernel-config.sh
check: lint lint-build-warnings
lint:
@status=0; \
$(MAKE) lint-checkpatch || status=$$?; \
$(MAKE) lint-format || status=$$?; \
exit $$status
lint-checkpatch:
git diff --no-ext-diff $(LINT_BASE) -- $(PCI_SIM_CHECKPATCH_PATHS) | \
$(PERL) $(PWD)/tools/checkpatch.pl --no-signoff --strict \
--show-types \
--ignore OPEN_ENDED_LINE,CONSTANT_COMPARISON \
--ignore LINUX_VERSION_CODE,EMBEDDED_FILENAME,FILE_PATH_CHANGES \
--no-tree --no-spelling --patch -
lint-format:
@if ! command -v git-clang-format >/dev/null 2>&1; then \
echo "git-clang-format is required for incremental format checks"; \
exit 1; \
fi
git clang-format --extensions c,h $(LINT_BASE) -- \
$(PCI_SIM_FORMAT_FILES)
@if ! git diff --quiet -- $(PCI_SIM_FORMAT_FILES); then \
echo "git clang-format updated files; review and include them"; \
git diff -- $(PCI_SIM_FORMAT_FILES); \
exit 1; \
fi
lint-build-warnings:
$(MAKE) W=1 test-build
$(MAKE) clean
# Non-privileged build validation for CI and local development.
test-build: modules
# Run host-side tests. Requires sudo and a kernel that supports module loading.
# Build the module first with 'make modules'.
test: test-loopback test-multi-pf
test: test-build test-host
test-host: test-loopback test-multi-pf
test-loopback:
sudo -n python3 $(PWD)/test_pci_sim_loopback.py --reload --unload \
+2
View File
@@ -1,3 +1,5 @@
.. SPDX-License-Identifier: GPL-2.0-only
Fake PCI SR-IOV VFIO test fixture
=================================
+40 -47
View File
@@ -19,7 +19,6 @@
#include <linux/iommu.h>
#include <linux/slab.h>
#include <linux/mutex.h>
#include <linux/idr.h>
#include <linux/xarray.h>
#include <linux/serial_reg.h>
#include <linux/tty.h>
@@ -39,48 +38,40 @@
#include <linux/pci-ecam.h>
#endif
/* =========================================================================
* Device identification
* ========================================================================= */
/* Device identification */
#define FAKE_PCI_VENDOR_ID 0x1d55
#define FAKE_PCI_PF_DEVICE_ID 0x1000
#define FAKE_PCI_VF_DEVICE_ID 0x1001
#define FAKE_PCI_SERIAL_CLASS 0x070002 /* Serial controller, 16550 */
#define FAKE_PCI_VENDOR_CLASS 0xff0000
#define FAKE_PCI_SUBSYS_VENDOR FAKE_PCI_VENDOR_ID
#define FAKE_PCI_SUBSYS_ID FAKE_PCI_PF_DEVICE_ID
#define FAKE_PCI_VENDOR_ID 0x1d55
#define FAKE_PCI_PF_DEVICE_ID 0x1000
#define FAKE_PCI_VF_DEVICE_ID 0x1001
#define FAKE_PCI_SERIAL_CLASS 0x070002 /* Serial controller, 16550 */
#define FAKE_PCI_VENDOR_CLASS 0xff0000
#define FAKE_PCI_SUBSYS_VENDOR FAKE_PCI_VENDOR_ID
#define FAKE_PCI_SUBSYS_ID FAKE_PCI_PF_DEVICE_ID
/* =========================================================================
* SR-IOV / BAR configuration
* ========================================================================= */
/* SR-IOV / BAR configuration */
#define MAX_VFS 7
#define FAKE_PCI_MAX_HOSTS 16
#define SRIOV_CAP_OFFSET 0x100
#define PCIE_CAP_OFFSET 0x40
#define MAX_VFS 7
#define FAKE_PCI_MAX_HOSTS 16
#define SRIOV_CAP_OFFSET 0x100
#define PCIE_CAP_OFFSET 0x40
#define BAR0_SIZE 0x1000
#define FAKE_PCI_MEM_BASE 0xd0000000ULL
#define FAKE_PCI_MEM_64_BASE 0x100000000ULL
#define FAKE_PCI_MEM_STRIDE 0x00100000
#define FAKE_PCI_MEM_MIN_SIZE (BAR0_SIZE * (MAX_VFS + 1))
#define FAKE_PCI_BAR_FLAGS PCI_BASE_ADDRESS_MEM_TYPE_64
#define PCI_SIM_VFIO_BAR0_SIZE 0x40000
#define PCI_SIM_SGI_IOC3_UART_OFFSET 0x20178
#define BAR0_SIZE 0x1000
#define FAKE_PCI_MEM_BASE 0xd0000000ULL
#define FAKE_PCI_MEM_64_BASE 0x100000000ULL
#define FAKE_PCI_MEM_STRIDE 0x00100000
#define FAKE_PCI_MEM_MIN_SIZE (BAR0_SIZE * (MAX_VFS + 1))
#define FAKE_PCI_BAR_FLAGS PCI_BASE_ADDRESS_MEM_TYPE_64
#define PCI_SIM_VFIO_BAR0_SIZE 0x40000
#define PCI_SIM_SGI_IOC3_UART_OFFSET 0x20178
/* =========================================================================
* Host-side TTY loopback
* ========================================================================= */
/* Host-side TTY loopback */
#define PCI_SIM_TTY_NAME "ttyPCI_SIM"
#define PCI_SIM_MAX_TTYS 256
#define PCI_SIM_UART_FIFO_SIZE 4096
#define PCI_SIM_UART_CHUNK 256
#define PCI_SIM_TTY_NAME "ttyPCI_SIM"
#define PCI_SIM_MAX_TTYS 256
#define PCI_SIM_UART_FIFO_SIZE 4096
#define PCI_SIM_UART_CHUNK 256
/* =========================================================================
* Data structures
* ========================================================================= */
/* Data structures */
struct fake_pci_device {
u8 config_space[4096];
@@ -105,11 +96,11 @@ struct fake_pci_host {
struct fake_pci_device vfs[MAX_VFS];
int num_vfs_enabled;
int domain_nr;
struct mutex lock;
struct mutex lock; /* Protects VF enable/disable state. */
};
struct pci_sim_uart {
spinlock_t lock;
spinlock_t lock; /* Protects UART registers and FIFO state. */
u8 regs[8];
u8 fifo[PCI_SIM_UART_FIFO_SIZE];
unsigned int head;
@@ -125,7 +116,7 @@ struct pci_sim_uart {
struct pci_sim_vf_tty {
struct pci_dev *pdev;
struct tty_port port;
struct mutex state_lock;
struct mutex state_lock; /* Protects dead flag and tty writes. */
struct pci_sim_uart uart;
int id;
bool dead;
@@ -133,13 +124,11 @@ struct pci_sim_vf_tty {
struct pci_sim_vfio_vf {
struct vfio_pci_core_device core;
struct mutex lock;
struct mutex lock; /* Serializes VFIO BAR0 access. */
struct pci_sim_uart uart;
};
/* =========================================================================
* Cross-file globals (defined in the owning .c, declared extern here)
* ========================================================================= */
/* Cross-file globals (defined in the owning .c, declared extern here) */
/* fake_pci_sriov_core.c */
extern struct list_head fake_hosts;
@@ -155,9 +144,7 @@ extern unsigned long mem_stride;
extern struct iommu_device fake_iommu_dev;
extern struct platform_device *fake_iommu_pdev;
/* =========================================================================
* Cross-file function declarations
* ========================================================================= */
/* Cross-file function declarations */
/* fake_pci_sriov_cfg.c */
void init_pf_config_space(struct fake_pci_device *dev);
@@ -170,7 +157,8 @@ void pci_sim_tty_unregister_driver(void);
/* UART primitives also used by vfio.c */
void pci_sim_uart_reset(struct pci_sim_uart *uart);
void pci_sim_uart_init(struct pci_sim_uart *uart);
size_t pci_sim_uart_write_data(struct pci_sim_uart *uart, const u8 *buf, size_t len);
size_t pci_sim_uart_write_data(struct pci_sim_uart *uart, const u8 *buf,
size_t len);
unsigned int pci_sim_uart_write_room(struct pci_sim_uart *uart);
unsigned int pci_sim_uart_chars_in_buffer(struct pci_sim_uart *uart);
u8 pci_sim_uart_lsr(struct pci_sim_uart *uart);
@@ -184,4 +172,9 @@ extern const struct iommu_ops fake_iommu_ops;
/* fake_pci_sriov_cfg.c (pci_ops used by core host-probe) */
extern struct pci_ops fake_pci_ops;
/* PCI drivers registered by core init */
extern struct pci_driver fake_pci_pf_driver;
extern struct pci_driver pci_sim_vf_driver;
extern struct pci_driver pci_sim_vfio_driver;
#endif /* FAKE_PCI_SRIOV_H */
+29 -36
View File
@@ -8,9 +8,7 @@
#include "fake_pci_sriov.h"
/* =========================================================================
* Config-space byte helpers
* ========================================================================= */
/* Config-space byte helpers */
static u16 fake_cfg_read16(const u8 *config, int where)
{
@@ -67,9 +65,7 @@ static int fake_cfg_write(u8 *config, int where, int size, u32 val)
}
}
/* =========================================================================
* Host-lookup helpers (used by iommu.c and pci_ops below)
* ========================================================================= */
/* Host-lookup helpers (used by iommu.c and pci_ops below) */
struct fake_pci_host *fake_pci_host_from_domain(int domain)
{
@@ -85,9 +81,7 @@ struct fake_pci_host *fake_pci_host_from_domain(int domain)
return NULL;
}
/* =========================================================================
* PCI capability initialisation
* ========================================================================= */
/* PCI capability initialisation */
static void fake_pci_set_class(u8 *config, u32 class)
{
@@ -152,7 +146,7 @@ static int fake_pci_write_bar(u8 *config, int where, u32 val, int base)
} else {
fake_cfg_write32(config, where,
(val & ~(BAR0_SIZE - 1)) |
FAKE_PCI_BAR_FLAGS);
FAKE_PCI_BAR_FLAGS);
}
return PCIBIOS_SUCCESSFUL;
}
@@ -178,7 +172,8 @@ void init_pf_config_space(struct fake_pci_device *dev)
fake_cfg_write16(config, PCI_VENDOR_ID, FAKE_PCI_VENDOR_ID);
fake_cfg_write16(config, PCI_DEVICE_ID, FAKE_PCI_PF_DEVICE_ID);
fake_cfg_write16(config, PCI_COMMAND,
PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
PCI_COMMAND_IO | PCI_COMMAND_MEMORY |
PCI_COMMAND_MASTER);
fake_cfg_write16(config, PCI_STATUS, PCI_STATUS_CAP_LIST);
config[PCI_REVISION_ID] = 0x01;
@@ -188,7 +183,8 @@ void init_pf_config_space(struct fake_pci_device *dev)
fake_cfg_write32(config, PCI_BASE_ADDRESS_0, FAKE_PCI_BAR_FLAGS);
fake_cfg_write32(config, PCI_BASE_ADDRESS_1, 0);
fake_cfg_write16(config, PCI_SUBSYSTEM_VENDOR_ID, FAKE_PCI_SUBSYS_VENDOR);
fake_cfg_write16(config, PCI_SUBSYSTEM_VENDOR_ID,
FAKE_PCI_SUBSYS_VENDOR);
fake_cfg_write16(config, PCI_SUBSYSTEM_ID, FAKE_PCI_SUBSYS_ID);
config[PCI_CAPABILITY_LIST] = PCIE_CAP_OFFSET;
@@ -211,18 +207,20 @@ static void init_vf_config_space(struct fake_pci_device *dev, int vf_index)
fake_cfg_write16(config, PCI_VENDOR_ID, FAKE_PCI_VENDOR_ID);
fake_cfg_write16(config, PCI_DEVICE_ID, FAKE_PCI_VF_DEVICE_ID);
fake_cfg_write16(config, PCI_COMMAND,
PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
PCI_COMMAND_IO | PCI_COMMAND_MEMORY |
PCI_COMMAND_MASTER);
fake_cfg_write16(config, PCI_STATUS, PCI_STATUS_CAP_LIST);
config[PCI_REVISION_ID] = 0x01;
fake_pci_set_class(config, vf_serial_class ? FAKE_PCI_SERIAL_CLASS :
FAKE_PCI_VENDOR_CLASS);
FAKE_PCI_VENDOR_CLASS);
config[PCI_CACHE_LINE_SIZE] = 64 / 4;
config[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_NORMAL;
fake_cfg_write32(config, PCI_BASE_ADDRESS_0, FAKE_PCI_BAR_FLAGS);
fake_cfg_write32(config, PCI_BASE_ADDRESS_1, 0);
fake_cfg_write16(config, PCI_SUBSYSTEM_VENDOR_ID, FAKE_PCI_SUBSYS_VENDOR);
fake_cfg_write16(config, PCI_SUBSYSTEM_VENDOR_ID,
FAKE_PCI_SUBSYS_VENDOR);
fake_cfg_write16(config, PCI_SUBSYSTEM_ID, FAKE_PCI_SUBSYS_ID);
config[PCI_CAPABILITY_LIST] = PCIE_CAP_OFFSET;
@@ -230,9 +228,7 @@ static void init_vf_config_space(struct fake_pci_device *dev, int vf_index)
init_pcie_capability(config, false);
}
/* =========================================================================
* pci_ops: config-space read/write
* ========================================================================= */
/* pci_ops: config-space read/write */
static struct fake_pci_device *get_fake_device(struct fake_pci_host *host,
unsigned int devfn)
@@ -300,7 +296,7 @@ static bool fake_pci_is_sriov_cfg(int where)
{
return where >= SRIOV_CAP_OFFSET &&
where < SRIOV_CAP_OFFSET + PCI_SRIOV_BAR +
PCI_SRIOV_NUM_BARS * 4;
PCI_SRIOV_NUM_BARS * 4;
}
static int fake_pci_write_config(struct pci_bus *bus, unsigned int devfn,
@@ -336,7 +332,8 @@ static int fake_pci_write_config(struct pci_bus *bus, unsigned int devfn,
if (size == 4 && where >= PCI_BASE_ADDRESS_0 &&
where < PCI_BASE_ADDRESS_5 + 4) {
ret = fake_pci_write_bar(config, where, val, PCI_BASE_ADDRESS_0);
ret = fake_pci_write_bar(config, where, val,
PCI_BASE_ADDRESS_0);
goto out_unlock;
}
@@ -348,8 +345,7 @@ static int fake_pci_write_config(struct pci_bus *bus, unsigned int devfn,
if (size == 4 && !dev->is_vf &&
where >= SRIOV_CAP_OFFSET + PCI_SRIOV_BAR &&
where < SRIOV_CAP_OFFSET + PCI_SRIOV_BAR +
PCI_SRIOV_NUM_BARS * 4) {
where < SRIOV_CAP_OFFSET + PCI_SRIOV_BAR + PCI_SRIOV_NUM_BARS * 4) {
ret = fake_pci_write_bar(config, where, val,
SRIOV_CAP_OFFSET + PCI_SRIOV_BAR);
goto out_unlock;
@@ -382,13 +378,11 @@ out_unlock:
}
struct pci_ops fake_pci_ops = {
.read = fake_pci_read_config,
.write = fake_pci_write_config,
.read = fake_pci_read_config,
.write = fake_pci_write_config,
};
/* =========================================================================
* SR-IOV VF enable/disable
* ========================================================================= */
/* SR-IOV VF enable/disable */
static void handle_sriov_numvfs_write(struct fake_pci_host *host, u16 num_vfs)
{
@@ -414,14 +408,13 @@ static void handle_sriov_numvfs_write(struct fake_pci_host *host, u16 num_vfs)
}
host->num_vfs_enabled = num_vfs;
fake_cfg_write16(pf_config, SRIOV_CAP_OFFSET + PCI_SRIOV_NUM_VF, num_vfs);
fake_cfg_write16(pf_config, SRIOV_CAP_OFFSET + PCI_SRIOV_NUM_VF,
num_vfs);
mutex_unlock(&host->lock);
}
/* =========================================================================
* PF driver
* ========================================================================= */
/* PF driver */
static struct fake_pci_host *fake_pci_host_from_pdev(struct pci_dev *pdev)
{
@@ -495,14 +488,14 @@ static int fake_pci_sriov_configure(struct pci_dev *pdev, int num_vfs)
static const struct pci_device_id fake_pci_pf_ids[] = {
{ PCI_DEVICE(FAKE_PCI_VENDOR_ID, FAKE_PCI_PF_DEVICE_ID) },
{ }
{}
};
MODULE_DEVICE_TABLE(pci, fake_pci_pf_ids);
struct pci_driver fake_pci_pf_driver = {
.name = "fake_pci_sriov_pf",
.id_table = fake_pci_pf_ids,
.probe = fake_pci_pf_probe,
.remove = fake_pci_pf_remove,
.name = "fake_pci_sriov_pf",
.id_table = fake_pci_pf_ids,
.probe = fake_pci_pf_probe,
.remove = fake_pci_pf_remove,
.sriov_configure = fake_pci_sriov_configure,
};
+3 -3
View File
@@ -15,21 +15,21 @@
*/
/* iommu_domain_ops.attach_dev gained the previous-domain argument later. */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 15, 0)
#if KERNEL_VERSION(6, 15, 0) <= LINUX_VERSION_CODE
#define PCI_SIM_IOMMU_ATTACH_HAS_OLD_DOMAIN 1
#else
#define PCI_SIM_IOMMU_ATTACH_HAS_OLD_DOMAIN 0
#endif
/* iommu_ops.domain_alloc_paging_flags and IOMMU_HWPT_ALLOC_PASID are newer. */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 15, 0)
#if KERNEL_VERSION(6, 15, 0) <= LINUX_VERSION_CODE
#define PCI_SIM_IOMMU_HAS_DOMAIN_ALLOC_PAGING_FLAGS 1
#else
#define PCI_SIM_IOMMU_HAS_DOMAIN_ALLOC_PAGING_FLAGS 0
#endif
/* VFIO grew optional region-info and PASID/token callbacks after 6.12. */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 15, 0)
#if KERNEL_VERSION(6, 15, 0) <= LINUX_VERSION_CODE
#define PCI_SIM_VFIO_HAS_GET_REGION_INFO_CAPS 1
#define PCI_SIM_VFIO_HAS_MATCH_TOKEN_UUID 1
#define PCI_SIM_VFIO_HAS_PASID_IOAS 1
+34 -39
View File
@@ -10,55 +10,51 @@
#include "fake_pci_sriov.h"
/* =========================================================================
* Module parameters
* ========================================================================= */
/* Module parameters */
bool vf_serial_class;
module_param(vf_serial_class, bool, 0644);
MODULE_PARM_DESC(vf_serial_class,
"Expose host-visible VFs as PCI serial/16550 class devices instead of vendor-specific");
MODULE_PARM_DESC(
vf_serial_class,
"Expose host-visible VFs as PCI serial/16550 class devices instead of vendor-specific");
bool vfio_guest_8250_compat = true;
module_param(vfio_guest_8250_compat, bool, 0644);
MODULE_PARM_DESC(vfio_guest_8250_compat,
"Overlay VFIO guest config space with an 8250_pci-compatible SGI IOC3 serial identity");
MODULE_PARM_DESC(
vfio_guest_8250_compat,
"Overlay VFIO guest config space with an 8250_pci-compatible SGI IOC3 serial identity");
bool vfio_uart_trace;
module_param(vfio_uart_trace, bool, 0644);
MODULE_PARM_DESC(vfio_uart_trace,
"Trace VFIO BAR0 UART register accesses");
MODULE_PARM_DESC(vfio_uart_trace, "Trace VFIO BAR0 UART register accesses");
static int fake_intx_irq;
module_param(fake_intx_irq, int, 0644);
MODULE_PARM_DESC(fake_intx_irq,
"Optional host IRQ number to report for fake PCI INTx routing (0 disables)");
MODULE_PARM_DESC(
fake_intx_irq,
"Optional host IRQ number to report for fake PCI INTx routing (0 disables)");
static unsigned int num_pfs = 1;
module_param(num_pfs, uint, 0444);
MODULE_PARM_DESC(num_pfs,
"Number of fake SR-IOV PFs to create");
MODULE_PARM_DESC(num_pfs, "Number of fake SR-IOV PFs to create");
static unsigned long mem_base;
module_param(mem_base, ulong, 0444);
MODULE_PARM_DESC(mem_base,
"Fixed fake PCI MMIO window base address (0 chooses automatically)");
MODULE_PARM_DESC(
mem_base,
"Fixed fake PCI MMIO window base address (0 chooses automatically)");
unsigned long mem_stride = FAKE_PCI_MEM_STRIDE;
module_param(mem_stride, ulong, 0444);
MODULE_PARM_DESC(mem_stride,
"Size and alignment of each fake PCI host MMIO window");
/* =========================================================================
* Global host list (also used by cfg.c and iommu.c)
* ========================================================================= */
/* Global host list (also used by cfg.c and iommu.c) */
LIST_HEAD(fake_hosts);
DEFINE_MUTEX(fake_hosts_lock);
DEFINE_MUTEX(fake_hosts_lock); /* Protects fake_hosts. */
/* =========================================================================
* PCI host bridge helpers
* ========================================================================= */
/* PCI host bridge helpers */
static void *fake_pci_host_sysdata(struct fake_pci_host *host)
{
@@ -101,7 +97,7 @@ static void fake_pci_host_release_mem_resource(struct fake_pci_host *host)
}
static int fake_pci_alloc_mem_resource(struct fake_pci_host *host,
resource_size_t stride)
resource_size_t stride)
{
static const struct {
resource_size_t start;
@@ -125,8 +121,8 @@ static int fake_pci_alloc_mem_resource(struct fake_pci_host *host,
host->mem_resource.flags |= IORESOURCE_MEM_64;
ret = allocate_resource(&iomem_resource, &host->mem_resource,
stride, regions[i].start, regions[i].end,
stride, NULL, NULL);
stride, regions[i].start,
regions[i].end, stride, NULL, NULL);
if (!ret) {
host->mem_resource_registered = true;
pr_info("fake_pci: allocated %s MMIO window [%#llx-%#llx]\n",
@@ -178,7 +174,8 @@ static int fake_pci_host_init_mem_resource(struct fake_pci_host *host,
ret = fake_pci_alloc_mem_resource(host, stride);
if (ret)
pr_err("fake_pci: failed to allocate any MMIO window: %d\n", ret);
pr_err("fake_pci: failed to allocate any MMIO window: %d\n",
ret);
return ret;
}
@@ -286,14 +283,7 @@ static void fake_pci_remove_all_hosts(void)
fake_pci_host_remove(host);
}
/* Forward declarations for drivers registered in init */
extern struct pci_driver fake_pci_pf_driver;
extern struct pci_driver pci_sim_vf_driver;
extern struct pci_driver pci_sim_vfio_driver;
/* =========================================================================
* Module init / exit
* ========================================================================= */
/* Module init / exit */
static int __init fake_pci_sriov_init(void)
{
@@ -316,7 +306,8 @@ static int __init fake_pci_sriov_init(void)
fake_iommu_pdev = platform_device_register_full(&pdevinfo);
if (IS_ERR(fake_iommu_pdev)) {
err = PTR_ERR(fake_iommu_pdev);
pr_err("fake_pci: Failed to register IOMMU platform device: %d\n", err);
pr_err("fake_pci: Failed to register IOMMU platform device: %d\n",
err);
return err;
}
@@ -344,13 +335,15 @@ static int __init fake_pci_sriov_init(void)
err = pci_register_driver(&pci_sim_vfio_driver);
if (err) {
pr_err("fake_pci: Failed to register VFIO UART driver: %d\n", err);
pr_err("fake_pci: Failed to register VFIO UART driver: %d\n",
err);
goto err_tty;
}
err = pci_register_driver(&pci_sim_vf_driver);
if (err) {
pr_err("fake_pci: Failed to register VF loopback driver: %d\n", err);
pr_err("fake_pci: Failed to register VF loopback driver: %d\n",
err);
goto err_vfio_driver;
}
@@ -387,7 +380,8 @@ static int __init fake_pci_sriov_init(void)
}
}
pr_info("fake_pci: Module loaded successfully with %u PF(s)\n", num_pfs);
pr_info("fake_pci: Module loaded successfully with %u PF(s)\n",
num_pfs);
pr_info("fake_pci: Use 'echo N > /sys/bus/pci/devices/.../sriov_numvfs' to enable VFs\n");
return 0;
@@ -433,4 +427,5 @@ module_exit(fake_pci_sriov_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("OpenStack Contributors");
MODULE_DESCRIPTION("Fake PCI Host Controller with Software IOMMU for SR-IOV Testing");
MODULE_DESCRIPTION(
"Fake PCI Host Controller with Software IOMMU for SR-IOV Testing");
+17 -16
View File
@@ -24,9 +24,10 @@ static struct fake_iommu_domain *to_fake_domain(struct iommu_domain *dom)
static int fake_domain_attach(struct iommu_domain *domain, struct device *dev
#if PCI_SIM_IOMMU_ATTACH_HAS_OLD_DOMAIN
, struct iommu_domain *old
,
struct iommu_domain *old
#endif
)
)
{
dev_dbg(dev, "fake_iommu: attached to domain type %u\n", domain->type);
return 0;
@@ -129,11 +130,11 @@ static phys_addr_t fake_domain_iova_to_phys(struct iommu_domain *domain,
}
static const struct iommu_domain_ops fake_paging_domain_ops = {
.attach_dev = fake_domain_attach,
.free = fake_domain_free_paging,
.map_pages = fake_domain_map_pages,
.unmap_pages = fake_domain_unmap_pages,
.iova_to_phys = fake_domain_iova_to_phys,
.attach_dev = fake_domain_attach,
.free = fake_domain_free_paging,
.map_pages = fake_domain_map_pages,
.unmap_pages = fake_domain_unmap_pages,
.iova_to_phys = fake_domain_iova_to_phys,
};
static struct iommu_domain *fake_domain_alloc_paging_common(void)
@@ -227,16 +228,16 @@ static struct iommu_group *fake_iommu_device_group(struct device *dev)
}
const struct iommu_ops fake_iommu_ops = {
.owner = THIS_MODULE,
.default_domain = &fake_blocking_domain,
.blocked_domain = &fake_blocking_domain,
.capable = fake_iommu_capable,
.probe_device = fake_iommu_probe_device,
.release_device = fake_iommu_release_device,
.device_group = fake_iommu_device_group,
.owner = THIS_MODULE,
.default_domain = &fake_blocking_domain,
.blocked_domain = &fake_blocking_domain,
.capable = fake_iommu_capable,
.probe_device = fake_iommu_probe_device,
.release_device = fake_iommu_release_device,
.device_group = fake_iommu_device_group,
#if PCI_SIM_IOMMU_HAS_DOMAIN_ALLOC_PAGING_FLAGS
.domain_alloc_paging_flags = fake_domain_alloc_paging_flags,
.domain_alloc_paging_flags = fake_domain_alloc_paging_flags,
#else
.domain_alloc_paging = fake_domain_alloc_paging,
.domain_alloc_paging = fake_domain_alloc_paging,
#endif
};
+46 -52
View File
@@ -11,13 +11,11 @@
#include "fake_pci_sriov.h"
static DEFINE_IDR(pci_sim_tty_idr);
static DEFINE_MUTEX(pci_sim_tty_idr_lock);
static DEFINE_XARRAY_ALLOC(pci_sim_tty_xa);
static DEFINE_MUTEX(pci_sim_tty_xa_lock); /* Serializes TTY ID lookup/removal. */
static struct tty_driver *pci_sim_tty_driver;
/* =========================================================================
* 16550-compatible UART emulation
* ========================================================================= */
/* 16550-compatible UART emulation */
void pci_sim_uart_reset(struct pci_sim_uart *uart)
{
@@ -49,8 +47,8 @@ static unsigned int pci_sim_uart_space_locked(struct pci_sim_uart *uart)
return PCI_SIM_UART_FIFO_SIZE - uart->count;
}
size_t pci_sim_uart_write_data(struct pci_sim_uart *uart,
const u8 *buf, size_t len)
size_t pci_sim_uart_write_data(struct pci_sim_uart *uart, const u8 *buf,
size_t len)
{
unsigned long flags;
size_t copied, i;
@@ -289,9 +287,7 @@ void pci_sim_uart_write_reg(struct pci_sim_uart *uart, u8 reg, u8 val)
}
}
/* =========================================================================
* VF TTY loopback helper
* ========================================================================= */
/* VF TTY loopback helper */
static void pci_sim_vf_flush_to_tty(struct pci_sim_vf_tty *vf)
{
@@ -306,7 +302,8 @@ static void pci_sim_vf_flush_to_tty(struct pci_sim_vf_tty *vf)
break;
pending = pci_sim_uart_peek_data(&vf->uart, buf,
min_t(size_t, sizeof(buf), room));
min_t(size_t, sizeof(buf),
room));
if (!pending)
break;
@@ -325,9 +322,7 @@ static void pci_sim_vf_flush_to_tty(struct pci_sim_vf_tty *vf)
tty_flip_buffer_push(&vf->port);
}
/* =========================================================================
* TTY driver operations
* ========================================================================= */
/* TTY driver operations */
static int pci_sim_tty_install(struct tty_driver *driver,
struct tty_struct *tty)
@@ -336,13 +331,13 @@ static int pci_sim_tty_install(struct tty_driver *driver,
struct tty_port *port;
int ret;
mutex_lock(&pci_sim_tty_idr_lock);
vf = idr_find(&pci_sim_tty_idr, tty->index);
mutex_lock(&pci_sim_tty_xa_lock);
vf = xa_load(&pci_sim_tty_xa, tty->index);
if (vf)
port = tty_port_get(&vf->port);
else
port = NULL;
mutex_unlock(&pci_sim_tty_idr_lock);
mutex_unlock(&pci_sim_tty_xa_lock);
if (!port)
return -ENODEV;
@@ -427,25 +422,25 @@ static void pci_sim_tty_hangup(struct tty_struct *tty)
}
static const struct tty_operations pci_sim_tty_ops = {
.install = pci_sim_tty_install,
.open = pci_sim_tty_open,
.close = pci_sim_tty_close,
.write = pci_sim_tty_write,
.write_room = pci_sim_tty_write_room,
.install = pci_sim_tty_install,
.open = pci_sim_tty_open,
.close = pci_sim_tty_close,
.write = pci_sim_tty_write,
.write_room = pci_sim_tty_write_room,
.chars_in_buffer = pci_sim_tty_chars_in_buffer,
.hangup = pci_sim_tty_hangup,
.cleanup = pci_sim_tty_cleanup,
.hangup = pci_sim_tty_hangup,
.cleanup = pci_sim_tty_cleanup,
};
static void pci_sim_tty_destruct_port(struct tty_port *port)
{
struct pci_sim_vf_tty *vf = container_of(port, struct pci_sim_vf_tty,
port);
struct pci_sim_vf_tty *vf =
container_of(port, struct pci_sim_vf_tty, port);
mutex_lock(&pci_sim_tty_idr_lock);
mutex_lock(&pci_sim_tty_xa_lock);
if (vf->id >= 0)
idr_remove(&pci_sim_tty_idr, vf->id);
mutex_unlock(&pci_sim_tty_idr_lock);
xa_erase(&pci_sim_tty_xa, vf->id);
mutex_unlock(&pci_sim_tty_xa_lock);
kfree(vf);
}
@@ -454,15 +449,14 @@ static const struct tty_port_operations pci_sim_tty_port_ops = {
.destruct = pci_sim_tty_destruct_port,
};
/* =========================================================================
* VF PCI driver
* ========================================================================= */
/* VF PCI driver */
static int pci_sim_vf_probe(struct pci_dev *pdev,
const struct pci_device_id *id)
{
struct pci_sim_vf_tty *vf;
struct device *tty_dev;
u32 tty_id;
int ret;
ret = pci_enable_device(pdev);
@@ -480,12 +474,13 @@ static int pci_sim_vf_probe(struct pci_dev *pdev,
mutex_init(&vf->state_lock);
pci_sim_uart_init(&vf->uart);
mutex_lock(&pci_sim_tty_idr_lock);
ret = idr_alloc(&pci_sim_tty_idr, vf, 0, PCI_SIM_MAX_TTYS, GFP_KERNEL);
mutex_unlock(&pci_sim_tty_idr_lock);
if (ret < 0)
mutex_lock(&pci_sim_tty_xa_lock);
ret = xa_alloc(&pci_sim_tty_xa, &tty_id, vf,
XA_LIMIT(0, PCI_SIM_MAX_TTYS - 1), GFP_KERNEL);
mutex_unlock(&pci_sim_tty_xa_lock);
if (ret)
goto err_free;
vf->id = ret;
vf->id = tty_id;
tty_port_init(&vf->port);
vf->port.ops = &pci_sim_tty_port_ops;
@@ -498,8 +493,8 @@ static int pci_sim_vf_probe(struct pci_dev *pdev,
}
pci_set_drvdata(pdev, vf);
pci_info(pdev, "registered /dev/%s%d, lsr=0x%02x\n",
PCI_SIM_TTY_NAME, vf->id, pci_sim_uart_lsr(&vf->uart));
pci_info(pdev, "registered /dev/%s%d, lsr=0x%02x\n", PCI_SIM_TTY_NAME,
vf->id, pci_sim_uart_lsr(&vf->uart));
return 0;
@@ -534,27 +529,26 @@ static void pci_sim_vf_remove(struct pci_dev *pdev)
static const struct pci_device_id pci_sim_vf_ids[] = {
{ PCI_DEVICE(FAKE_PCI_VENDOR_ID, FAKE_PCI_VF_DEVICE_ID) },
{ }
{}
};
MODULE_DEVICE_TABLE(pci, pci_sim_vf_ids);
struct pci_driver pci_sim_vf_driver = {
.name = "pci_sim_loopback_vf",
.id_table = pci_sim_vf_ids,
.probe = pci_sim_vf_probe,
.remove = pci_sim_vf_remove,
.name = "pci_sim_loopback_vf",
.id_table = pci_sim_vf_ids,
.probe = pci_sim_vf_probe,
.remove = pci_sim_vf_remove,
};
/* =========================================================================
* TTY driver registration (called from core init/exit)
* ========================================================================= */
/* TTY driver registration (called from core init/exit) */
int pci_sim_tty_register_driver(void)
{
int ret;
pci_sim_tty_driver = tty_alloc_driver(PCI_SIM_MAX_TTYS,
TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV);
pci_sim_tty_driver =
tty_alloc_driver(PCI_SIM_MAX_TTYS,
TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV);
if (IS_ERR(pci_sim_tty_driver))
return PTR_ERR(pci_sim_tty_driver);
@@ -565,8 +559,8 @@ int pci_sim_tty_register_driver(void)
pci_sim_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
pci_sim_tty_driver->subtype = SERIAL_TYPE_NORMAL;
pci_sim_tty_driver->init_termios = tty_std_termios;
pci_sim_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD |
HUPCL | CLOCAL;
pci_sim_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL |
CLOCAL;
pci_sim_tty_driver->init_termios.c_lflag &= ~(ECHO | ICANON);
pci_sim_tty_driver->init_termios.c_oflag &= ~(OPOST | ONLCR);
@@ -589,5 +583,5 @@ void pci_sim_tty_unregister_driver(void)
tty_unregister_driver(pci_sim_tty_driver);
tty_driver_kref_put(pci_sim_tty_driver);
pci_sim_tty_driver = NULL;
idr_destroy(&pci_sim_tty_idr);
xa_destroy(&pci_sim_tty_xa);
}
+46 -42
View File
@@ -15,8 +15,8 @@
static int pci_sim_vfio_open_device(struct vfio_device *core_vdev)
{
struct pci_sim_vfio_vf *sim = container_of(core_vdev,
struct pci_sim_vfio_vf, core.vdev);
struct pci_sim_vfio_vf *sim =
container_of(core_vdev, struct pci_sim_vfio_vf, core.vdev);
int ret;
ret = vfio_pci_core_enable(&sim->core);
@@ -72,14 +72,17 @@ static ssize_t pci_sim_vfio_bar0_rw(struct pci_sim_vfio_vf *sim,
if (vfio_uart_trace)
pr_info("fake_pci: vfio uart W off=0x%llx reg=%u val=0x%02x\n",
(unsigned long long)(pos + done), reg, val);
(unsigned long long)(pos + done), reg,
val);
pci_sim_uart_write_reg(&sim->uart, reg, val);
} else {
if (pci_sim_vfio_bar0_uart_reg(pos + done, &reg)) {
val = pci_sim_uart_read_reg(&sim->uart, reg);
if (vfio_uart_trace)
pr_info("fake_pci: vfio uart R off=0x%llx reg=%u val=0x%02x\n",
(unsigned long long)(pos + done), reg, val);
(unsigned long long)(pos +
done),
reg, val);
} else {
val = 0xff;
}
@@ -95,17 +98,16 @@ static ssize_t pci_sim_vfio_bar0_rw(struct pci_sim_vfio_vf *sim,
return done;
}
static int pci_sim_vfio_copy_config_value(char __user *buf,
loff_t pos, size_t count,
unsigned int reg, const void *val,
size_t val_size)
static int pci_sim_vfio_copy_config_value(char __user *buf, loff_t pos,
size_t count, unsigned int reg,
const void *val, size_t val_size)
{
loff_t copy_offset;
size_t copy_count, register_offset;
if (!vfio_pci_core_range_intersect_range(pos, count, reg, val_size,
&copy_offset, &copy_count,
&register_offset))
&copy_offset, &copy_count,
&register_offset))
return 0;
if (copy_to_user(buf + copy_offset, val + register_offset, copy_count))
@@ -146,8 +148,8 @@ static ssize_t pci_sim_vfio_read_config(struct vfio_device *core_vdev,
val16 = cpu_to_le16(0xff00);
if (pci_sim_vfio_copy_config_value(buf, pos, done,
PCI_SUBSYSTEM_VENDOR_ID,
&val16, sizeof(val16)))
PCI_SUBSYSTEM_VENDOR_ID, &val16,
sizeof(val16)))
return -EFAULT;
val16 = cpu_to_le16(0);
@@ -161,8 +163,8 @@ static ssize_t pci_sim_vfio_read_config(struct vfio_device *core_vdev,
static ssize_t pci_sim_vfio_read(struct vfio_device *core_vdev,
char __user *buf, size_t count, loff_t *ppos)
{
struct pci_sim_vfio_vf *sim = container_of(core_vdev,
struct pci_sim_vfio_vf, core.vdev);
struct pci_sim_vfio_vf *sim =
container_of(core_vdev, struct pci_sim_vfio_vf, core.vdev);
unsigned int index = VFIO_PCI_OFFSET_TO_INDEX(*ppos);
if (!count)
@@ -181,8 +183,8 @@ static ssize_t pci_sim_vfio_write(struct vfio_device *core_vdev,
const char __user *buf, size_t count,
loff_t *ppos)
{
struct pci_sim_vfio_vf *sim = container_of(core_vdev,
struct pci_sim_vfio_vf, core.vdev);
struct pci_sim_vfio_vf *sim =
container_of(core_vdev, struct pci_sim_vfio_vf, core.vdev);
unsigned int index = VFIO_PCI_OFFSET_TO_INDEX(*ppos);
if (!count)
@@ -204,7 +206,8 @@ static int pci_sim_vfio_get_region_info(struct vfio_device *core_vdev,
return vfio_pci_ioctl_get_region_info(core_vdev, info, caps);
info->offset = VFIO_PCI_INDEX_TO_OFFSET(info->index);
info->size = vfio_guest_8250_compat ? PCI_SIM_VFIO_BAR0_SIZE : BAR0_SIZE;
info->size = vfio_guest_8250_compat ? PCI_SIM_VFIO_BAR0_SIZE :
BAR0_SIZE;
info->flags = VFIO_REGION_INFO_FLAG_READ | VFIO_REGION_INFO_FLAG_WRITE;
return 0;
}
@@ -242,7 +245,8 @@ static long pci_sim_vfio_ioctl(struct vfio_device *core_vdev, unsigned int cmd,
static int pci_sim_vfio_mmap(struct vfio_device *core_vdev,
struct vm_area_struct *vma)
{
unsigned int index = vma->vm_pgoff >> (VFIO_PCI_OFFSET_SHIFT - PAGE_SHIFT);
unsigned int index = vma->vm_pgoff >>
(VFIO_PCI_OFFSET_SHIFT - PAGE_SHIFT);
if (index == VFIO_PCI_BAR0_REGION_INDEX)
return -EINVAL;
@@ -251,30 +255,30 @@ static int pci_sim_vfio_mmap(struct vfio_device *core_vdev,
}
static const struct vfio_device_ops pci_sim_vfio_ops = {
.name = "pci_sim_vfio_pci",
.init = vfio_pci_core_init_dev,
.release = vfio_pci_core_release_dev,
.open_device = pci_sim_vfio_open_device,
.close_device = vfio_pci_core_close_device,
.name = "pci_sim_vfio_pci",
.init = vfio_pci_core_init_dev,
.release = vfio_pci_core_release_dev,
.open_device = pci_sim_vfio_open_device,
.close_device = vfio_pci_core_close_device,
#if PCI_SIM_VFIO_HAS_GET_REGION_INFO_CAPS
.ioctl = vfio_pci_core_ioctl,
.ioctl = vfio_pci_core_ioctl,
.get_region_info_caps = pci_sim_vfio_get_region_info,
#else
.ioctl = pci_sim_vfio_ioctl,
.ioctl = pci_sim_vfio_ioctl,
#endif
.device_feature = vfio_pci_core_ioctl_feature,
.read = pci_sim_vfio_read,
.write = pci_sim_vfio_write,
.mmap = pci_sim_vfio_mmap,
.request = vfio_pci_core_request,
.match = vfio_pci_core_match,
.device_feature = vfio_pci_core_ioctl_feature,
.read = pci_sim_vfio_read,
.write = pci_sim_vfio_write,
.mmap = pci_sim_vfio_mmap,
.request = vfio_pci_core_request,
.match = vfio_pci_core_match,
#if PCI_SIM_VFIO_HAS_MATCH_TOKEN_UUID
.match_token_uuid = vfio_pci_core_match_token_uuid,
#endif
.bind_iommufd = vfio_iommufd_physical_bind,
.unbind_iommufd = vfio_iommufd_physical_unbind,
.attach_ioas = vfio_iommufd_physical_attach_ioas,
.detach_ioas = vfio_iommufd_physical_detach_ioas,
.bind_iommufd = vfio_iommufd_physical_bind,
.unbind_iommufd = vfio_iommufd_physical_unbind,
.attach_ioas = vfio_iommufd_physical_attach_ioas,
.detach_ioas = vfio_iommufd_physical_detach_ioas,
#if PCI_SIM_VFIO_HAS_PASID_IOAS
.pasid_attach_ioas = vfio_iommufd_physical_pasid_attach_ioas,
.pasid_detach_ioas = vfio_iommufd_physical_pasid_detach_ioas,
@@ -324,15 +328,15 @@ static void pci_sim_vfio_remove(struct pci_dev *pdev)
static const struct pci_device_id pci_sim_vfio_ids[] = {
{ PCI_DRIVER_OVERRIDE_DEVICE_VFIO(FAKE_PCI_VENDOR_ID,
FAKE_PCI_VF_DEVICE_ID) },
{ }
{}
};
MODULE_DEVICE_TABLE(pci, pci_sim_vfio_ids);
struct pci_driver pci_sim_vfio_driver = {
.name = "pci_sim_vfio_pci",
.id_table = pci_sim_vfio_ids,
.probe = pci_sim_vfio_probe,
.remove = pci_sim_vfio_remove,
.err_handler = &vfio_pci_core_err_handlers,
.driver_managed_dma = true,
.name = "pci_sim_vfio_pci",
.id_table = pci_sim_vfio_ids,
.probe = pci_sim_vfio_probe,
.remove = pci_sim_vfio_remove,
.err_handler = &vfio_pci_core_err_handlers,
.driver_managed_dma = true,
};
+202
View File
@@ -0,0 +1,202 @@
.. SPDX-License-Identifier: GPL-2.0-only
Kernel conventions for pci-sim
==============================
This document defines the local coding conventions and validation checks for
``pci-sim``. ``pci-sim`` is an out-of-tree kernel module, but it should be
written and reviewed like Linux kernel code so that it remains maintainable and
can track upstream PCI, SR-IOV, VFIO, IOMMU, and TTY APIs.
The Linux kernel documentation and nearby subsystem code are the source of
truth. In particular, consult:
* ``Documentation/process/coding-style.rst``
* ``Documentation/process/submit-checklist.rst``
* ``Documentation/process/submitting-patches.rst``
* ``Documentation/dev-tools/checkpatch.rst``
* ``Documentation/dev-tools/clang-format.rst``
* ``Documentation/PCI/pci.rst``
* ``Documentation/PCI/pci-iov-howto.rst``
* ``Documentation/driver-api/vfio.rst``
Required local checks
---------------------
Run these before posting or merging pci-sim changes.
Build the module
~~~~~~~~~~~~~~~~
From ``pci-sim/``::
make test-build
make clean
The build must complete without new warnings. Run ``make clean`` before
finishing local validation so generated module artifacts are not left behind.
Run lint
~~~~~~~~
Run the local pci-sim lint target against the diff from ``origin/master``::
make lint
``make lint`` runs the repo-supported style checks for normal review: the
vendored Linux ``checkpatch.pl`` in patch mode with ``--no-spelling`` and
``git clang-format`` for C and header changes. The format check updates the
working tree when formatting changes are needed, then fails so the developer
can review and include those formatting updates. The local ``.clang-format``
copy is tuned to reduce immediate post-``(" line breaks, but lint still
ignores ``OPEN_ENDED_LINE`` because ``clang-format`` can produce that
checkpatch advisory for long module metadata macros. It also ignores
``CONSTANT_COMPARISON`` and
``LINUX_VERSION_CODE`` for the isolated out-of-tree compatibility header,
``EMBEDDED_FILENAME`` for the Makefile lint path list, and
``FILE_PATH_CHANGES`` because pci-sim ownership is tracked by the Cyborg
repository rather than the Linux kernel ``MAINTAINERS`` file. Spelling is
handled by the repository's top-level ``codespell`` pre-commit hook, not by
checkpatch.
``checkpatch.pl`` is a guide, not an absolute authority. New errors should be
fixed. New warnings and checks should either be fixed or explicitly justified
in review.
The local lint target runs ``checkpatch.pl`` with ``--no-tree``. That keeps
the check self-contained and avoids extra Linux-tree helper
dependencies, but it means complete SPDX expression validation is not part of
the initial lint gate.
Run full checks
~~~~~~~~~~~~~~~
Before posting pci-sim changes, run::
make check
``make check`` runs ``make lint`` and then builds the module with the kernel
``W=1`` extra-warning level. It cleans generated module artifacts after the
build.
Run behavior tests for behavior changes
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
For changes that affect runtime behavior, run the relevant smoke tests, for
example::
make test-loopback
make test-multi-pf
Also run the VFIO, QEMU, or CirrOS helper tests when touching those paths.
A style-clean build is not sufficient for PCI, VFIO, or IOMMU behavior
changes.
Formatter policy
----------------
``clang-format`` is useful, but formatting churn must be controlled.
* A one-time normalization with ``clang-format`` is acceptable if it is a
dedicated formatting-only change.
* Use the ``.clang-format`` file provided in this repository. It was
imported from the Linux kernel formatting configuration so contributors do
not need a separate Linux kernel checkout.
* Review the resulting diff manually for correctness and readability. The
imported ``.clang-format`` approximates kernel style but is not perfect.
* Do not mix formatting-only churn with functional changes.
* After any normalization commit, format only new or touched code.
* Prefer the repository ``clang-format`` output for pci-sim formatting. The
goal is close alignment with kernel style, but consistent automated
formatting is more important than preserving hand-aligned exceptions.
* Do not use ``scripts/Lindent`` as an automated formatter for pci-sim.
Developer coding conventions
----------------------------
General kernel style
~~~~~~~~~~~~~~~~~~~~
* Use tabs for indentation. Kernel indentation is 8 columns.
* Prefer 80-column lines. Do not split user-visible log strings solely to fit
the limit because that makes them harder to grep.
* Use normal kernel brace style: opening braces stay on the control statement
line, while function opening braces go on the next line.
* Use lower-case names with underscores. Global symbols should be descriptive;
local variables can be short when the scope is small.
* Avoid typedefs for structs and pointers.
* Prefer inline functions over macros when type checking or single evaluation
matters. Keep macros for constants, compile-time constructs, and cases where
an inline function cannot work.
* Include the header that directly declares the API being used. Do not rely on
unrelated headers to include it indirectly.
* Keep functions short, focused, and shallowly indented. Split functions that
mix setup, emulation, cleanup, and policy decisions.
* Use direct returns when no cleanup is required. Use ``goto`` cleanup labels
for multi-step allocation or registration paths, and name labels after the
cleanup they perform.
* Comments should explain purpose, constraints, hardware behavior, locking,
ordering, or ABI. Do not restate obvious code.
* Document every module parameter with ``MODULE_PARM_DESC()``.
pci-sim structure
~~~~~~~~~~~~~~~~~
* Keep subsystem ownership clear. PCI config-space emulation, host bridge
setup, IOMMU grouping, VFIO behavior, UART emulation, polling threads, and
tests should remain separated by responsibility.
* Avoid compatibility sprawl. If kernel-version compatibility is required,
isolate it in compatibility helpers or headers and keep normal code readable.
* Avoid broad abstraction layers that hide Linux kernel APIs without adding a
real pci-sim concept.
* Treat sysfs files, module parameters, helper-script behavior, and
guest-visible device behavior as user-visible interfaces. Keep them stable
unless changing them is intentional and documented.
Ownership, lifetime, and cleanup
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* For every object, identify the owner and release path: host bridge, PCI
resource, VF state, IOMMU object, VFIO device, TTY port, backing file,
kthread, and allocated memory.
* Registration and allocation error paths must unwind in reverse order.
* Remove and module-exit paths must tolerate partially initialized state.
* Repeated load, test, failure, cleanup, and reload cycles should be reliable.
* Helper scripts should be idempotent and safe to run after partial failures.
Locking and concurrency
~~~~~~~~~~~~~~~~~~~~~~~
* Protect shared mutable state with the narrowest suitable kernel lock.
* Document lock ordering where more than one lock can be held.
* Review races between module unload, PF removal, VF enable/disable, VFIO MMIO
access, TTY operations, kthreads, and cleanup scripts.
* Memory barriers and non-obvious ordering rules require comments explaining
what they pair with and why they are needed.
PCI, SR-IOV, VFIO, and IOMMU expectations
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Follow the kernel SR-IOV model around ``sriov_numvfs``: validate VF counts,
reject invalid transitions, and cleanly remove VFs before disabling state.
* Keep VF personalities isolated so adding or changing UART behavior does not
destabilize VFIO, IOMMU, or host-bridge behavior.
* Preserve VFIO isolation assumptions. Review IOMMU group behavior, DMA
mapping assumptions, BAR emulation, interrupt delivery, and reset semantics.
* Prefer debuggable correctness over clever emulation shortcuts.
Review checklist
----------------
Before considering a pci-sim change ready, verify:
* The change solves one logical problem.
* Formatting-only changes are separated from functional changes.
* The module builds and generated artifacts have been cleaned.
* ``checkpatch.pl`` has no new unhandled errors, warnings, or checks.
* Relevant build-warning gaps are reported.
* Runtime tests cover the paths affected by the change.
* Allocation, registration, error, remove, and unload paths are correct.
* Locking and object lifetimes are understandable from the code.
* New or changed module parameters, helper behavior, or user-visible behavior
are documented.
+7890
View File
File diff suppressed because it is too large. Load diff
+113
View File
@@ -0,0 +1,113 @@
acpi_dock_ops
address_space_operations
backlight_ops
bin_attribute
block_device_operations
bus_type
clk_ops
comedi_lrange
component_ops
ctl_table
dentry_operations
dev_pm_ops
device_type
dma_map_ops
driver_info
drm_connector_funcs
drm_encoder_funcs
drm_encoder_helper_funcs
dvb_frontend_ops
dvb_tuner_ops
ethtool_ops
extent_io_ops
fb_ops
file_lock_operations
file_operations
hv_ops
hwmon_ops
ib_device_ops
ide_dma_ops
ide_port_ops
ieee80211_ops
iio_buffer_setup_ops
inode_operations
intel_dvo_dev_ops
irq_domain_ops
item_operations
iwl_cfg
iwl_ops
kernel_param_ops
kgdb_arch
kgdb_io
kobj_type
kset_uevent_ops
lcd_ops
lock_manager_operations
machine_desc
microcode_ops
mlxsw_reg_info
mtd_ooblayout_ops
mtrr_ops
nand_controller_ops
neigh_ops
net_device_ops
nft_expr_ops
nlmsvc_binding
nvkm_device_chip
of_device_id
pci_raw_ops
phy_ops
pinconf_ops
pinctrl_ops
pinmux_ops
pipe_buf_operations
platform_hibernation_ops
platform_suspend_ops
proc_ops
proto_ops
pwm_ops
reg_default
reg_field
reg_sequence
regmap_access_table
regmap_bus
regmap_config
regmap_irq
regmap_irq_chip
regmap_irq_sub_irq_map
regmap_range
regmap_range_cfg
regulator_ops
reset_control_ops
rpc_pipe_ops
rtc_class_ops
sd_desc
sdhci_ops
seq_operations
sirfsoc_padmux
snd_ac97_build_ops
snd_pcm_ops
snd_rawmidi_ops
snd_soc_component_driver
snd_soc_dai_ops
snd_soc_ops
snd_soc_tplg_ops
soc_pcmcia_socket_ops
stacktrace_ops
sysfs_ops
tty_operations
uart_ops
usb_mon_operations
v4l2_ctrl_ops
v4l2_ioctl_ops
v4l2_subdev_core_ops
v4l2_subdev_internal_ops
v4l2_subdev_ops
v4l2_subdev_pad_ops
v4l2_subdev_video_ops
vb2_ops
vm_operations_struct
wacom_features
watchdog_ops
wd_ops
xattr_handler