Commit d41771b2 authored by Srinivas Pandruvada's avatar Srinivas Pandruvada Committed by Jia, Yingbao
Browse files

platform/x86/intel/tpmi: Add debugfs support for read/write blocked

mainline inclusion
from mainline-v6.8
commit 8df012a7f513141412b3c35af204ccdb810fcc81
category: bugfix
bugzilla: https://gitee.com/openeuler/intel-kernel/issues/IB6QCJ
CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=8df012a7f513141412b3c35af204ccdb810fcc81



-------------------------------------------------

Intel-SIG: commit 8df012a7f513 platform/x86/intel/tpmi: Add debugfs support for read/write blocked.
Backport intel tpmi base driver update for 6.6 from 6.10

Display read and write blocked status of each TPMI feature in addition
to disabled and locked status.

This will require reading of read/write blocked state from the hardware.
Currently tpmi_read_feature_status(), doesn't provide this state.

Define TPMI feature state as defined in the TPMI spec. Modify the function
tpmi_read_feature_status() to update full feature state instead of just
disabled and locked state.

Signed-off-by: default avatarSrinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
Link: https://lore.kernel.org/r/20230925194219.966602-1-srinivas.pandruvada@linux.intel.com


Reviewed-by: default avatarIlpo Järvinen <ilpo.jarvinen@linux.intel.com>
Signed-off-by: default avatarIlpo Järvinen <ilpo.jarvinen@linux.intel.com>
[ Yingbao Jia: amend commit log ]
Signed-off-by: default avatarYingbao Jia <yingbao.jia@intel.com>
parent 26835b36
Loading
Loading
Loading
Loading
+55 −25
Original line number Diff line number Diff line
@@ -143,6 +143,33 @@ struct tpmi_info_header {
	u64 lock:1;
} __packed;

/**
 * struct tpmi_feature_state - Structure to read hardware state of a feature
 * @enabled:	Enable state of a feature, 1: enabled, 0: disabled
 * @reserved_1:	Reserved for future use
 * @write_blocked: Writes are blocked means all write operations are ignored
 * @read_blocked: Reads are blocked means will read 0xFFs
 * @pcs_select:	Interface used by out of band software, not used in OS
 * @reserved_2:	Reserved for future use
 * @id:		TPMI ID of the feature
 * @reserved_3:	Reserved for future use
 * @locked:	When set to 1, OS can't change this register.
 *
 * The structure is used to read hardware state of a TPMI feature. This
 * information is used for debug and restricting operations for this feature.
 */
struct tpmi_feature_state {
	u32 enabled:1;
	u32 reserved_1:3;
	u32 write_blocked:1;
	u32 read_blocked:1;
	u32 pcs_select:1;
	u32 reserved_2:1;
	u32 id:8;
	u32 reserved_3:15;
	u32 locked:1;
} __packed;

/*
 * List of supported TMPI IDs.
 * Some TMPI IDs are not used by Linux, so the numbers are not consecutive.
@@ -202,6 +229,7 @@ EXPORT_SYMBOL_NS_GPL(tpmi_get_resource_at_index, INTEL_TPMI);

#define TPMI_CONTROL_STATUS_OFFSET	0x00
#define TPMI_COMMAND_OFFSET		0x08
#define TMPI_CONTROL_DATA_VAL_OFFSET	0x0c

/*
 * Spec is calling for max 1 seconds to get ownership at the worst
@@ -230,7 +258,6 @@ EXPORT_SYMBOL_NS_GPL(tpmi_get_resource_at_index, INTEL_TPMI);

/* TPMI command data registers */
#define TMPI_CONTROL_DATA_CMD		GENMASK_ULL(7, 0)
#define TMPI_CONTROL_DATA_VAL		GENMASK_ULL(63, 32)
#define TPMI_CONTROL_DATA_VAL_FEATURE	GENMASK_ULL(48, 40)

/* Command to send via control interface */
@@ -240,9 +267,6 @@ EXPORT_SYMBOL_NS_GPL(tpmi_get_resource_at_index, INTEL_TPMI);

#define TPMI_CMD_LEN_MASK		GENMASK_ULL(18, 16)

#define TPMI_STATE_DISABLED		BIT_ULL(0)
#define TPMI_STATE_LOCKED		BIT_ULL(31)

/* Mutex to complete get feature status without interruption */
static DEFINE_MUTEX(tpmi_dev_lock);

@@ -256,7 +280,7 @@ static int tpmi_wait_for_owner(struct intel_tpmi_info *tpmi_info, u8 owner)
}

static int tpmi_read_feature_status(struct intel_tpmi_info *tpmi_info, int feature_id,
				    int *locked, int *disabled)
				    struct tpmi_feature_state *feature_state)
{
	u64 control, data;
	int ret;
@@ -306,17 +330,8 @@ static int tpmi_read_feature_status(struct intel_tpmi_info *tpmi_info, int featu
	}

	/* Response is ready */
	data = readq(tpmi_info->tpmi_control_mem + TPMI_COMMAND_OFFSET);
	data = FIELD_GET(TMPI_CONTROL_DATA_VAL, data);

	*disabled = 0;
	*locked = 0;

	if (!(data & TPMI_STATE_DISABLED))
		*disabled = 1;

	if (data & TPMI_STATE_LOCKED)
		*locked = 1;
	memcpy_fromio(feature_state, tpmi_info->tpmi_control_mem + TMPI_CONTROL_DATA_VAL_OFFSET,
		      sizeof(*feature_state));

	ret = 0;

@@ -335,34 +350,49 @@ int tpmi_get_feature_status(struct auxiliary_device *auxdev, int feature_id,
{
	struct intel_vsec_device *intel_vsec_dev = dev_to_ivdev(auxdev->dev.parent);
	struct intel_tpmi_info *tpmi_info = auxiliary_get_drvdata(&intel_vsec_dev->auxdev);
	struct tpmi_feature_state feature_state;
	int ret;

	ret = tpmi_read_feature_status(tpmi_info, feature_id, &feature_state);
	if (ret)
		return ret;

	*locked = feature_state.locked;
	*disabled = !feature_state.enabled;

	return tpmi_read_feature_status(tpmi_info, feature_id, locked, disabled);
	return 0;
}
EXPORT_SYMBOL_NS_GPL(tpmi_get_feature_status, INTEL_TPMI);

static int tpmi_pfs_dbg_show(struct seq_file *s, void *unused)
{
	struct intel_tpmi_info *tpmi_info = s->private;
	int locked, disabled, read_blocked, write_blocked;
	struct tpmi_feature_state feature_state;
	struct intel_tpmi_pm_feature *pfs;
	int locked, disabled, ret, i;
	int ret, i;

	seq_printf(s, "tpmi PFS start offset 0x:%llx\n", tpmi_info->pfs_start);
	seq_puts(s, "tpmi_id\t\tentries\t\tsize\t\tcap_offset\tattribute\tvsec_offset\tlocked\tdisabled\n");
	seq_puts(s, "tpmi_id\t\tentries\t\tsize\t\tcap_offset\tattribute\tvsec_offset\tlocked\tdisabled\tread_blocked\twrite_blocked\n");
	for (i = 0; i < tpmi_info->feature_count; ++i) {
		pfs = &tpmi_info->tpmi_features[i];
		ret = tpmi_read_feature_status(tpmi_info, pfs->pfs_header.tpmi_id, &locked,
					       &disabled);
		ret = tpmi_read_feature_status(tpmi_info, pfs->pfs_header.tpmi_id, &feature_state);
		if (ret) {
			locked = 'U';
			disabled = 'U';
			read_blocked = 'U';
			write_blocked = 'U';
		} else {
			disabled = disabled ? 'Y' : 'N';
			locked = locked ? 'Y' : 'N';
			disabled = feature_state.enabled ? 'N' : 'Y';
			locked = feature_state.locked ? 'Y' : 'N';
			read_blocked = feature_state.read_blocked ? 'Y' : 'N';
			write_blocked = feature_state.write_blocked ? 'Y' : 'N';
		}
		seq_printf(s, "0x%02x\t\t0x%02x\t\t0x%04x\t\t0x%04x\t\t0x%02x\t\t0x%016llx\t%c\t%c\n",
		seq_printf(s, "0x%02x\t\t0x%02x\t\t0x%04x\t\t0x%04x\t\t0x%02x\t\t0x%016llx\t%c\t%c\t\t%c\t\t%c\n",
			   pfs->pfs_header.tpmi_id, pfs->pfs_header.num_entries,
			   pfs->pfs_header.entry_size, pfs->pfs_header.cap_offset,
			   pfs->pfs_header.attribute, pfs->vsec_offset, locked, disabled);
			   pfs->pfs_header.attribute, pfs->vsec_offset, locked, disabled,
			   read_blocked, write_blocked);
	}

	return 0;