Files
s390-tools/rust/cpacfinfo/src/main.rs
Marc Hartmayer f8fb9ce32a rust: Run rustfmt with some experimental options
+ Sort and group the imports
+ Normalize and format comments (100 characters width)

Command used:

$ cargo +nightly fmt --

Acked-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Marc Hartmayer <marc@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2026-06-22 16:43:02 +02:00

255 lines
8.5 KiB
Rust

// SPDX-License-Identifier: MIT
//
// Copyright IBM Corp. 2024
mod cli;
mod msa;
mod query;
mod stfle;
use std::io::ErrorKind;
use std::result::Result::Ok;
use anyhow::{bail, Result as anyhowRes};
use clap::Parser;
use utils::print_version;
use crate::cli::{Cli, Format};
use crate::msa::*;
use crate::query::*;
use crate::stfle::*;
/// producing -m/--msa output
fn out_msa(args: &Cli, levels: &Vec<MsaLevel>, instructions: &Vec<Instruction>) {
// produce json output
if args.format == Format::Json {
println!("{}", serde_json::to_string(levels).unwrap());
return;
}
// produce human readable output
for lvl in levels {
// print current level
println!("{lvl}");
// if -f/--functions is not specified continue to next level
if !args.functions {
continue;
}
// print all functions introduced by the current level sorted by instruction
for ins in instructions {
// skip instructions for which the current level introduces no new functions
if !args.instructions.contains(&ins.kind) && !args.instructions.is_empty()
|| !ins.info.available
{
continue;
}
// filter all functions that do not fit the command line arguments
let funcs_to_be_printed = ins
.funcs
.iter()
.filter(|func| {
!(!func.available && !args.not_available
|| func.available && !args.available && args.not_available)
})
.filter(|func| func.msa == lvl.msa_level);
// print all functions matching the command line arguments
let mut ins_printed = false;
for func in funcs_to_be_printed {
if !ins_printed {
println!("\t{ins}");
ins_printed = true;
}
println!("\t\t{func}");
}
}
}
}
/// produces output for all cpacfinfo commands that do not contain the -m/--msa flag
fn out_instructions(args: &Cli, instructions: &Vec<Instruction>) {
// produce json output
if args.format == Format::Json {
println!("{}", serde_json::to_string(instructions).unwrap());
return;
}
// produce human readable output
for ins in instructions {
if !args.instructions.contains(&ins.kind) && !args.instructions.is_empty()
|| !ins.info.available
{
continue;
}
println!("{ins}");
// --no-auth-info/-n suppresses the Authentication Information output
if !args.quiet && ins.info.qai_available {
println!("{}", ins.info.qai);
} else if !args.quiet {
println!("Query Authentication Information not available for {ins} instruction! (potentially insufficient machine level)");
}
// --functions/-f lists functions of instructions
if args.functions {
ins.funcs
.iter()
.filter(|func| {
!(!func.available && !args.not_available
|| func.available && !args.available && args.not_available)
})
.for_each(|func| println!("\t{func}"));
println!();
}
}
}
fn main() -> anyhowRes<()> {
// ---- PARSE COMMAND LINE ARGUMENTS ----
let args: Cli = Cli::parse();
// ---- PRINT VERSION STRING ----
if args.version {
print_version!("2024");
return Ok(());
}
// ---- SET CONSTANTS ----
let mut instructions = Vec::new();
init_instructions(&mut instructions);
let mut levels = Vec::new();
for lvl in 0..MSA_LEVEL_COUNT {
let temp = match num2msa(lvl) {
Some(l) => l,
None => panic!("programming error"),
};
let stfle_bit = msa2stfle(&temp);
levels.push(MsaLevel::new(temp, stfle_bit));
let idx_of_last_element = levels.len() - 1;
update_msa_function_count(&args, &mut levels[idx_of_last_element], &instructions);
}
// ---- GET INFORMATION ----
// get stfle bits
let stfle_bits = Stfle::new()?;
// check stfle bits for available MSA levels
for lvl in &mut levels {
match lvl.stfle_bit {
Some(bit) => lvl.enabled = stfle_bits.check_bit_in_stfle(bit),
None => continue,
}
}
// check if SYSFS_PATH is available
match check_sysfs() {
true => (),
false => return Ok(()),
}
// run query function (fc 0) for every instruction to check available functions
for ins in &mut instructions {
if stfle_bits.check_bit_in_stfle(ins.info.stfle_bit) {
ins.info.available = true;
// run query; save result in param
let mut param = match query(&ins.kind, QUERY_FUNCTION_CODE) {
Ok(pb) => match pb {
Param::QueryParam(_) => pb,
Param::QaiParam(_) => panic!("programming error"),
},
Err(e) => match e.kind() {
ErrorKind::NotFound => {
println!("Warning: Not able to retrieve subfunction information from sysfs for {ins} instruction");
continue;
}
_ => return Err(e.into()),
},
};
// check if bit for functions of current instruction is set in param
for func in &mut ins.funcs {
if !param.check_bit_in_param(func.function_code as usize) {
continue;
}
func.available = true;
// unset the bit in param to later see if any unsupported functions may be available
param.unset_bit_in_param(func.function_code);
// check if qai is available
if func.function_code == QAI_FUNCTION_CODE {
ins.info.qai_available = true;
}
// sync MsaLevel struct
for lvl in &mut levels {
if lvl.msa_level == func.msa {
lvl.enabled = true;
lvl.available_functions += 1;
if args.instructions.is_empty() || args.instructions.contains(&ins.kind) {
lvl.dynamic_available_functions += 1;
}
break;
}
}
}
// look for any unsupported functions that my be available
for i in 0..NUMBER_FUNC_CODES {
// every bit in param that is 1 is an unsupported function
if !param.check_bit_in_param(i) {
continue;
}
// add function to instruction as UNKNOWN
Instruction::add(ins, Function::new(i as u8, Msa::UNKNOWN, "UNKNOWN"));
// set function as available
match ins.funcs.last_mut() {
Some(ret) => ret.available = true,
None => panic!("programming error"),
}
}
// if query authentication information (fc 127) available run query authentication
// information
if ins.info.qai_available {
// get qai from sysfs
let param = match query(&ins.kind, QAI_FUNCTION_CODE) {
Ok(pb) => match pb {
Param::QueryParam(_) => panic!("programming error"),
Param::QaiParam(_) => pb,
},
Err(e) => match e.kind() {
ErrorKind::NotFound => {
println!("Warning: Not able to retrieve Query Authentication Information from sysfs for {ins} instruction");
continue;
}
_ => return Err(e.into()),
},
};
// parse qai information into QueryAuthInfo struct
match param.parse_qai_based_on_format(&mut ins.info.qai) {
Ok(true) => (),
Ok(false) => println!("WARNING: format {} in query authentication information of instruction {} is UNKNOWN", ins.info.qai.format, ins.kind),
Err(e) => bail!(e.to_string()),
}
}
}
}
// ---- OUTPUT ----
match args.msa {
true => out_msa(&args, &levels, &instructions),
false => out_instructions(&args, &instructions),
}
Ok(())
}