Commit a70210f4 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'x86_microcode_for_v6.2' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull x86 microcode and IFS updates from Borislav Petkov:
 "The IFS (In-Field Scan) stuff goes through tip because the IFS driver
  uses the same structures and similar functionality as the microcode
  loader and it made sense to route it all through this branch so that
  there are no conflicts.

   - Add support for multiple testing sequences to the Intel In-Field
     Scan driver in order to be able to run multiple different test
     patterns. Rework things and remove the BROKEN dependency so that
     the driver can be enabled (Jithu Joseph)

   - Remove the subsys interface usage in the microcode loader because
     it is not really needed

   - A couple of smaller fixes and cleanups"

* tag 'x86_microcode_for_v6.2' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (24 commits)
  x86/microcode/intel: Do not retry microcode reloading on the APs
  x86/microcode/intel: Do not print microcode revision and processor flags
  platform/x86/intel/ifs: Add missing kernel-doc entry
  Revert "platform/x86/intel/ifs: Mark as BROKEN"
  Documentation/ABI: Update IFS ABI doc
  platform/x86/intel/ifs: Add current_batch sysfs entry
  platform/x86/intel/ifs: Remove reload sysfs entry
  platform/x86/intel/ifs: Add metadata validation
  platform/x86/intel/ifs: Use generic microcode headers and functions
  platform/x86/intel/ifs: Add metadata support
  x86/microcode/intel: Use a reserved field for metasize
  x86/microcode/intel: Add hdr_type to intel_microcode_sanity_check()
  x86/microcode/intel: Reuse microcode_sanity_check()
  x86/microcode/intel: Use appropriate type in microcode_sanity_check()
  x86/microcode/intel: Reuse find_matching_signature()
  platform/x86/intel/ifs: Remove memory allocation from load path
  platform/x86/intel/ifs: Remove image loading during init
  platform/x86/intel/ifs: Return a more appropriate error code
  platform/x86/intel/ifs: Remove unused selection
  x86/microcode: Drop struct ucode_cpu_info.valid
  ...
parents 3ef3ace4 be1b670f
Loading
Loading
Loading
Loading
+16 −14
Original line number Diff line number Diff line
What:		/sys/devices/virtual/misc/intel_ifs_<N>/run_test
Date:		April 21 2022
KernelVersion:	5.19
Date:		Nov 16 2022
KernelVersion:	6.2
Contact:	"Jithu Joseph" <jithu.joseph@intel.com>
Description:	Write <cpu#> to trigger IFS test for one online core.
		Note that the test is per core. The cpu# can be
		for any thread on the core. Running on one thread
		completes the test for the core containing that thread.
		Example: to test the core containing cpu5: echo 5 >
		/sys/devices/platform/intel_ifs.<N>/run_test
		/sys/devices/virtual/misc/intel_ifs_<N>/run_test

What:		/sys/devices/virtual/misc/intel_ifs_<N>/status
Date:		April 21 2022
KernelVersion:	5.19
Date:		Nov 16 2022
KernelVersion:	6.2
Contact:	"Jithu Joseph" <jithu.joseph@intel.com>
Description:	The status of the last test. It can be one of "pass", "fail"
		or "untested".

What:		/sys/devices/virtual/misc/intel_ifs_<N>/details
Date:		April 21 2022
KernelVersion:	5.19
Date:		Nov 16 2022
KernelVersion:	6.2
Contact:	"Jithu Joseph" <jithu.joseph@intel.com>
Description:	Additional information regarding the last test. The details file reports
		the hex value of the SCAN_STATUS MSR. Note that the error_code field
		may contain driver defined software code not defined in the Intel SDM.

What:		/sys/devices/virtual/misc/intel_ifs_<N>/image_version
Date:		April 21 2022
KernelVersion:	5.19
Date:		Nov 16 2022
KernelVersion:	6.2
Contact:	"Jithu Joseph" <jithu.joseph@intel.com>
Description:	Version (hexadecimal) of loaded IFS binary image. If no scan image
		is loaded reports "none".

What:		/sys/devices/virtual/misc/intel_ifs_<N>/reload
Date:		April 21 2022
KernelVersion:	5.19
What:		/sys/devices/virtual/misc/intel_ifs_<N>/current_batch
Date:		Nov 16 2022
KernelVersion:	6.2
Contact:	"Jithu Joseph" <jithu.joseph@intel.com>
Description:	Write "1" (or "y" or "Y") to reload the IFS image from
		/lib/firmware/intel/ifs/ff-mm-ss.scan.
Description:	Write a number less than or equal to 0xff to load an IFS test image.
		The number written treated as the 2 digit suffix in the following file name:
		/lib/firmware/intel/ifs_<N>/ff-mm-ss-02x.scan
		Reading the file will provide the suffix of the currently loaded IFS test image.
+2 −0
Original line number Diff line number Diff line
@@ -95,5 +95,7 @@ static inline bool intel_cpu_signatures_match(unsigned int s1, unsigned int p1,
}

extern u64 x86_read_arch_cap_msr(void);
int intel_find_matching_signature(void *mc, unsigned int csig, int cpf);
int intel_microcode_sanity_check(void *mc, bool print_err, int hdr_type);

#endif /* _ASM_X86_CPU_H */
+1 −3
Original line number Diff line number Diff line
@@ -33,8 +33,7 @@ enum ucode_state {
};

struct microcode_ops {
	enum ucode_state (*request_microcode_fw) (int cpu, struct device *,
						  bool refresh_fw);
	enum ucode_state (*request_microcode_fw) (int cpu, struct device *);

	void (*microcode_fini_cpu) (int cpu);

@@ -50,7 +49,6 @@ struct microcode_ops {

struct ucode_cpu_info {
	struct cpu_signature	cpu_sig;
	int			valid;
	void			*mc;
};
extern struct ucode_cpu_info ucode_cpu_info[];
+4 −1
Original line number Diff line number Diff line
@@ -14,7 +14,8 @@ struct microcode_header_intel {
	unsigned int            pf;
	unsigned int            datasize;
	unsigned int            totalsize;
	unsigned int            reserved[3];
	unsigned int            metasize;
	unsigned int            reserved[2];
};

struct microcode_intel {
@@ -41,6 +42,8 @@ struct extended_sigtable {
#define DEFAULT_UCODE_TOTALSIZE (DEFAULT_UCODE_DATASIZE + MC_HEADER_SIZE)
#define EXT_HEADER_SIZE		(sizeof(struct extended_sigtable))
#define EXT_SIGNATURE_SIZE	(sizeof(struct extended_signature))
#define MC_HEADER_TYPE_MICROCODE	1
#define MC_HEADER_TYPE_IFS		2

#define get_totalsize(mc) \
	(((struct microcode_intel *)mc)->hdr.datasize ? \
+143 −1
Original line number Diff line number Diff line
@@ -210,12 +210,154 @@ int intel_cpu_collect_info(struct ucode_cpu_info *uci)
	csig.rev = intel_get_microcode_revision();

	uci->cpu_sig = csig;
	uci->valid = 1;

	return 0;
}
EXPORT_SYMBOL_GPL(intel_cpu_collect_info);

/*
 * Returns 1 if update has been found, 0 otherwise.
 */
int intel_find_matching_signature(void *mc, unsigned int csig, int cpf)
{
	struct microcode_header_intel *mc_hdr = mc;
	struct extended_sigtable *ext_hdr;
	struct extended_signature *ext_sig;
	int i;

	if (intel_cpu_signatures_match(csig, cpf, mc_hdr->sig, mc_hdr->pf))
		return 1;

	/* Look for ext. headers: */
	if (get_totalsize(mc_hdr) <= get_datasize(mc_hdr) + MC_HEADER_SIZE)
		return 0;

	ext_hdr = mc + get_datasize(mc_hdr) + MC_HEADER_SIZE;
	ext_sig = (void *)ext_hdr + EXT_HEADER_SIZE;

	for (i = 0; i < ext_hdr->count; i++) {
		if (intel_cpu_signatures_match(csig, cpf, ext_sig->sig, ext_sig->pf))
			return 1;
		ext_sig++;
	}
	return 0;
}
EXPORT_SYMBOL_GPL(intel_find_matching_signature);

/**
 * intel_microcode_sanity_check() - Sanity check microcode file.
 * @mc: Pointer to the microcode file contents.
 * @print_err: Display failure reason if true, silent if false.
 * @hdr_type: Type of file, i.e. normal microcode file or In Field Scan file.
 *            Validate if the microcode header type matches with the type
 *            specified here.
 *
 * Validate certain header fields and verify if computed checksum matches
 * with the one specified in the header.
 *
 * Return: 0 if the file passes all the checks, -EINVAL if any of the checks
 * fail.
 */
int intel_microcode_sanity_check(void *mc, bool print_err, int hdr_type)
{
	unsigned long total_size, data_size, ext_table_size;
	struct microcode_header_intel *mc_header = mc;
	struct extended_sigtable *ext_header = NULL;
	u32 sum, orig_sum, ext_sigcount = 0, i;
	struct extended_signature *ext_sig;

	total_size = get_totalsize(mc_header);
	data_size = get_datasize(mc_header);

	if (data_size + MC_HEADER_SIZE > total_size) {
		if (print_err)
			pr_err("Error: bad microcode data file size.\n");
		return -EINVAL;
	}

	if (mc_header->ldrver != 1 || mc_header->hdrver != hdr_type) {
		if (print_err)
			pr_err("Error: invalid/unknown microcode update format. Header type %d\n",
			       mc_header->hdrver);
		return -EINVAL;
	}

	ext_table_size = total_size - (MC_HEADER_SIZE + data_size);
	if (ext_table_size) {
		u32 ext_table_sum = 0;
		u32 *ext_tablep;

		if (ext_table_size < EXT_HEADER_SIZE ||
		    ((ext_table_size - EXT_HEADER_SIZE) % EXT_SIGNATURE_SIZE)) {
			if (print_err)
				pr_err("Error: truncated extended signature table.\n");
			return -EINVAL;
		}

		ext_header = mc + MC_HEADER_SIZE + data_size;
		if (ext_table_size != exttable_size(ext_header)) {
			if (print_err)
				pr_err("Error: extended signature table size mismatch.\n");
			return -EFAULT;
		}

		ext_sigcount = ext_header->count;

		/*
		 * Check extended table checksum: the sum of all dwords that
		 * comprise a valid table must be 0.
		 */
		ext_tablep = (u32 *)ext_header;

		i = ext_table_size / sizeof(u32);
		while (i--)
			ext_table_sum += ext_tablep[i];

		if (ext_table_sum) {
			if (print_err)
				pr_warn("Bad extended signature table checksum, aborting.\n");
			return -EINVAL;
		}
	}

	/*
	 * Calculate the checksum of update data and header. The checksum of
	 * valid update data and header including the extended signature table
	 * must be 0.
	 */
	orig_sum = 0;
	i = (MC_HEADER_SIZE + data_size) / sizeof(u32);
	while (i--)
		orig_sum += ((u32 *)mc)[i];

	if (orig_sum) {
		if (print_err)
			pr_err("Bad microcode data checksum, aborting.\n");
		return -EINVAL;
	}

	if (!ext_table_size)
		return 0;

	/*
	 * Check extended signature checksum: 0 => valid.
	 */
	for (i = 0; i < ext_sigcount; i++) {
		ext_sig = (void *)ext_header + EXT_HEADER_SIZE +
			  EXT_SIGNATURE_SIZE * i;

		sum = (mc_header->sig + mc_header->pf + mc_header->cksum) -
		      (ext_sig->sig + ext_sig->pf + ext_sig->cksum);
		if (sum) {
			if (print_err)
				pr_err("Bad extended signature checksum, aborting.\n");
			return -EINVAL;
		}
	}
	return 0;
}
EXPORT_SYMBOL_GPL(intel_microcode_sanity_check);

static void early_init_intel(struct cpuinfo_x86 *c)
{
	u64 misc_enable;
Loading