microcode_amd.c 10.9 KB
Newer Older
1 2
/*
 *  AMD CPU Microcode Update Driver for Linux
3
 *  Copyright (C) 2008-2011 Advanced Micro Devices Inc.
4 5 6 7 8 9
 *
 *  Author: Peter Oruba <peter.oruba@amd.com>
 *
 *  Based on work by:
 *  Tigran Aivazian <tigran@aivazian.fsnet.co.uk>
 *
10
 *  Maintainers:
11 12
 *  Andreas Herrmann <herrmann.der.user@googlemail.com>
 *  Borislav Petkov <bp@alien8.de>
13 14 15
 *
 *  This driver allows to upgrade microcode on F10h AMD
 *  CPUs and later.
16
 *
17
 *  Licensed under the terms of the GNU General Public
18
 *  License version 2. See file COPYING for details.
I
Ingo Molnar 已提交
19
 */
20 21 22

#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt

I
Ingo Molnar 已提交
23 24 25 26 27 28
#include <linux/firmware.h>
#include <linux/pci_ids.h>
#include <linux/uaccess.h>
#include <linux/vmalloc.h>
#include <linux/kernel.h>
#include <linux/module.h>
29 30 31
#include <linux/pci.h>

#include <asm/microcode.h>
I
Ingo Molnar 已提交
32 33
#include <asm/processor.h>
#include <asm/msr.h>
34
#include <asm/microcode_amd.h>
35 36

MODULE_DESCRIPTION("AMD Microcode Update Driver");
37
MODULE_AUTHOR("Peter Oruba");
38
MODULE_LICENSE("GPL v2");
39

D
Dmitry Adamushko 已提交
40
static struct equiv_cpu_entry *equiv_cpu_table;
41

42 43 44 45 46 47 48 49 50
struct ucode_patch {
	struct list_head plist;
	void *data;
	u32 patch_id;
	u16 equiv_cpu;
};

static LIST_HEAD(pcache);

51
static u16 __find_equiv_id(unsigned int cpu)
52 53
{
	struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
54
	return find_equiv_id(equiv_cpu_table, uci->cpu_sig.sig);
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
}

static u32 find_cpu_family_by_equiv_cpu(u16 equiv_cpu)
{
	int i = 0;

	BUG_ON(!equiv_cpu_table);

	while (equiv_cpu_table[i].equiv_cpu != 0) {
		if (equiv_cpu == equiv_cpu_table[i].equiv_cpu)
			return equiv_cpu_table[i].installed_cpu;
		i++;
	}
	return 0;
}

71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
/*
 * a small, trivial cache of per-family ucode patches
 */
static struct ucode_patch *cache_find_patch(u16 equiv_cpu)
{
	struct ucode_patch *p;

	list_for_each_entry(p, &pcache, plist)
		if (p->equiv_cpu == equiv_cpu)
			return p;
	return NULL;
}

static void update_cache(struct ucode_patch *new_patch)
{
	struct ucode_patch *p;

	list_for_each_entry(p, &pcache, plist) {
		if (p->equiv_cpu == new_patch->equiv_cpu) {
			if (p->patch_id >= new_patch->patch_id)
				/* we already have the latest patch */
				return;

			list_replace(&p->plist, &new_patch->plist);
			kfree(p->data);
			kfree(p);
			return;
		}
	}
	/* no patch found, add it */
	list_add_tail(&new_patch->plist, &pcache);
}

static void free_cache(void)
{
106
	struct ucode_patch *p, *tmp;
107

108
	list_for_each_entry_safe(p, tmp, &pcache, plist) {
109 110 111 112 113 114 115 116 117 118
		__list_del(p->plist.prev, p->plist.next);
		kfree(p->data);
		kfree(p);
	}
}

static struct ucode_patch *find_patch(unsigned int cpu)
{
	u16 equiv_id;

119
	equiv_id = __find_equiv_id(cpu);
120 121 122 123 124 125
	if (!equiv_id)
		return NULL;

	return cache_find_patch(equiv_id);
}

126
static int collect_cpu_info_amd(int cpu, struct cpu_signature *csig)
127
{
128
	struct cpuinfo_x86 *c = &cpu_data(cpu);
129 130
	struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
	struct ucode_patch *p;
131

132
	csig->sig = cpuid_eax(0x00000001);
133
	csig->rev = c->microcode;
134 135 136 137 138 139 140 141 142

	/*
	 * a patch could have been loaded early, set uci->mc so that
	 * mc_bp_resume() can call apply_microcode()
	 */
	p = find_patch(cpu);
	if (p && (p->patch_id == csig->rev))
		uci->mc = p->data;

143 144
	pr_info("CPU%d: patch_level=0x%08x\n", cpu, csig->rev);

145
	return 0;
146 147
}

148
static unsigned int verify_patch_size(u8 family, u32 patch_size,
149
				      unsigned int size)
150
{
151 152 153 154 155
	u32 max_size;

#define F1XH_MPB_MAX_SIZE 2048
#define F14H_MPB_MAX_SIZE 1824
#define F15H_MPB_MAX_SIZE 4096
156
#define F16H_MPB_MAX_SIZE 3458
157

158
	switch (family) {
159 160 161 162 163 164
	case 0x14:
		max_size = F14H_MPB_MAX_SIZE;
		break;
	case 0x15:
		max_size = F15H_MPB_MAX_SIZE;
		break;
165 166 167
	case 0x16:
		max_size = F16H_MPB_MAX_SIZE;
		break;
168 169 170 171 172 173 174 175 176 177 178 179 180
	default:
		max_size = F1XH_MPB_MAX_SIZE;
		break;
	}

	if (patch_size > min_t(u32, size, max_size)) {
		pr_err("patch size mismatch\n");
		return 0;
	}

	return patch_size;
}

181 182 183 184 185 186 187 188 189 190 191 192 193 194 195
int __apply_microcode_amd(struct microcode_amd *mc_amd)
{
	u32 rev, dummy;

	wrmsrl(MSR_AMD64_PATCH_LOADER, (u64)(long)&mc_amd->hdr.data_code);

	/* verify patch application was successful */
	rdmsr(MSR_AMD64_PATCH_LEVEL, rev, dummy);
	if (rev != mc_amd->hdr.patch_id)
		return -1;

	return 0;
}

int apply_microcode_amd(int cpu)
196
{
197
	struct cpuinfo_x86 *c = &cpu_data(cpu);
198 199 200 201 202 203
	struct microcode_amd *mc_amd;
	struct ucode_cpu_info *uci;
	struct ucode_patch *p;
	u32 rev, dummy;

	BUG_ON(raw_smp_processor_id() != cpu);
204

205
	uci = ucode_cpu_info + cpu;
206

207 208
	p = find_patch(cpu);
	if (!p)
209
		return 0;
210

211 212 213
	mc_amd  = p->data;
	uci->mc = p->data;

214
	rdmsr(MSR_AMD64_PATCH_LEVEL, rev, dummy);
215

216 217 218
	/* need to apply patch? */
	if (rev >= mc_amd->hdr.patch_id) {
		c->microcode = rev;
219
		uci->cpu_sig.rev = rev;
220 221 222
		return 0;
	}

223
	if (__apply_microcode_amd(mc_amd)) {
224
		pr_err("CPU%d: update failed for patch_level=0x%08x\n",
225
			cpu, mc_amd->hdr.patch_id);
226 227 228 229
		return -1;
	}
	pr_info("CPU%d: new patch_level=0x%08x\n", cpu,
		mc_amd->hdr.patch_id);
230

231 232
	uci->cpu_sig.rev = mc_amd->hdr.patch_id;
	c->microcode = mc_amd->hdr.patch_id;
233 234

	return 0;
235 236
}

237
static int install_equiv_cpu_table(const u8 *buf)
238
{
239 240 241
	unsigned int *ibuf = (unsigned int *)buf;
	unsigned int type = ibuf[1];
	unsigned int size = ibuf[2];
242

243
	if (type != UCODE_EQUIV_CPU_TABLE_TYPE || !size) {
244 245
		pr_err("empty section/"
		       "invalid type field in container file section header\n");
246
		return -EINVAL;
247 248
	}

249
	equiv_cpu_table = vmalloc(size);
250
	if (!equiv_cpu_table) {
251
		pr_err("failed to allocate equivalent CPU table\n");
252
		return -ENOMEM;
253 254
	}

255
	memcpy(equiv_cpu_table, buf + CONTAINER_HDR_SZ, size);
256

257 258
	/* add header length */
	return size + CONTAINER_HDR_SZ;
259 260
}

D
Dmitry Adamushko 已提交
261
static void free_equiv_cpu_table(void)
262
{
263 264
	vfree(equiv_cpu_table);
	equiv_cpu_table = NULL;
D
Dmitry Adamushko 已提交
265
}
266

267
static void cleanup(void)
D
Dmitry Adamushko 已提交
268
{
269 270 271 272 273 274 275 276 277 278 279
	free_equiv_cpu_table();
	free_cache();
}

/*
 * We return the current size even if some of the checks failed so that
 * we can skip over the next patch. If we return a negative value, we
 * signal a grave error like a memory allocation has failed and the
 * driver cannot continue functioning normally. In such cases, we tear
 * down everything we've used up so far and exit.
 */
280
static int verify_and_add_patch(u8 family, u8 *fw, unsigned int leftover)
281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300
{
	struct microcode_header_amd *mc_hdr;
	struct ucode_patch *patch;
	unsigned int patch_size, crnt_size, ret;
	u32 proc_fam;
	u16 proc_id;

	patch_size  = *(u32 *)(fw + 4);
	crnt_size   = patch_size + SECTION_HDR_SIZE;
	mc_hdr	    = (struct microcode_header_amd *)(fw + SECTION_HDR_SIZE);
	proc_id	    = mc_hdr->processor_rev_id;

	proc_fam = find_cpu_family_by_equiv_cpu(proc_id);
	if (!proc_fam) {
		pr_err("No patch family for equiv ID: 0x%04x\n", proc_id);
		return crnt_size;
	}

	/* check if patch is for the current family */
	proc_fam = ((proc_fam >> 8) & 0xf) + ((proc_fam >> 20) & 0xff);
301
	if (proc_fam != family)
302 303 304 305 306 307 308 309
		return crnt_size;

	if (mc_hdr->nb_dev_id || mc_hdr->sb_dev_id) {
		pr_err("Patch-ID 0x%08x: chipset-specific code unsupported.\n",
			mc_hdr->patch_id);
		return crnt_size;
	}

310
	ret = verify_patch_size(family, patch_size, leftover);
311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340
	if (!ret) {
		pr_err("Patch-ID 0x%08x: size mismatch.\n", mc_hdr->patch_id);
		return crnt_size;
	}

	patch = kzalloc(sizeof(*patch), GFP_KERNEL);
	if (!patch) {
		pr_err("Patch allocation failure.\n");
		return -EINVAL;
	}

	patch->data = kzalloc(patch_size, GFP_KERNEL);
	if (!patch->data) {
		pr_err("Patch data allocation failure.\n");
		kfree(patch);
		return -EINVAL;
	}

	/* All looks ok, copy patch... */
	memcpy(patch->data, fw + SECTION_HDR_SIZE, patch_size);
	INIT_LIST_HEAD(&patch->plist);
	patch->patch_id  = mc_hdr->patch_id;
	patch->equiv_cpu = proc_id;

	/* ... and add to cache. */
	update_cache(patch);

	return crnt_size;
}

341 342
static enum ucode_state __load_microcode_amd(u8 family, const u8 *data,
					     size_t size)
343 344 345 346 347
{
	enum ucode_state ret = UCODE_ERROR;
	unsigned int leftover;
	u8 *fw = (u8 *)data;
	int crnt_size = 0;
348
	int offset;
349

350
	offset = install_equiv_cpu_table(data);
351
	if (offset < 0) {
352
		pr_err("failed to create equivalent cpu table\n");
353
		return ret;
354
	}
355
	fw += offset;
D
Dmitry Adamushko 已提交
356 357
	leftover = size - offset;

358
	if (*(u32 *)fw != UCODE_UCODE_TYPE) {
359
		pr_err("invalid type field in container file section header\n");
360 361
		free_equiv_cpu_table();
		return ret;
362
	}
D
Dmitry Adamushko 已提交
363

364
	while (leftover) {
365
		crnt_size = verify_and_add_patch(family, fw, leftover);
366 367
		if (crnt_size < 0)
			return ret;
368

369 370
		fw	 += crnt_size;
		leftover -= crnt_size;
371
	}
D
Dmitry Adamushko 已提交
372

373
	return UCODE_OK;
D
Dmitry Adamushko 已提交
374 375
}

376
enum ucode_state load_microcode_amd(u8 family, const u8 *data, size_t size)
377 378 379 380 381 382
{
	enum ucode_state ret;

	/* free old equiv table */
	free_equiv_cpu_table();

383
	ret = __load_microcode_amd(family, data, size);
384 385 386 387

	if (ret != UCODE_OK)
		cleanup();

388 389
#if defined(CONFIG_MICROCODE_AMD_EARLY) && defined(CONFIG_X86_32)
	/* save BSP's matching patch for early load */
390 391
	if (cpu_data(smp_processor_id()).cpu_index == boot_cpu_data.cpu_index) {
		struct ucode_patch *p = find_patch(smp_processor_id());
392 393 394 395 396 397 398
		if (p) {
			memset(amd_bsp_mpb, 0, MPB_MAX_SIZE);
			memcpy(amd_bsp_mpb, p->data, min_t(u32, ksize(p->data),
							   MPB_MAX_SIZE));
		}
	}
#endif
399 400 401
	return ret;
}

402 403 404 405 406 407 408 409
/*
 * AMD microcode firmware naming convention, up to family 15h they are in
 * the legacy file:
 *
 *    amd-ucode/microcode_amd.bin
 *
 * This legacy file is always smaller than 2K in size.
 *
410
 * Beginning with family 15h, they are in family-specific firmware files:
411 412 413 414 415 416 417
 *
 *    amd-ucode/microcode_amd_fam15h.bin
 *    amd-ucode/microcode_amd_fam16h.bin
 *    ...
 *
 * These might be larger than 2K.
 */
418 419
static enum ucode_state request_microcode_amd(int cpu, struct device *device,
					      bool refresh_fw)
D
Dmitry Adamushko 已提交
420
{
421 422
	char fw_name[36] = "amd-ucode/microcode_amd.bin";
	struct cpuinfo_x86 *c = &cpu_data(cpu);
423 424 425 426 427 428
	enum ucode_state ret = UCODE_NFOUND;
	const struct firmware *fw;

	/* reload ucode container only on the boot cpu */
	if (!refresh_fw || c->cpu_index != boot_cpu_data.cpu_index)
		return UCODE_OK;
429 430 431

	if (c->x86 >= 0x15)
		snprintf(fw_name, sizeof(fw_name), "amd-ucode/microcode_amd_fam%.2xh.bin", c->x86);
D
Dmitry Adamushko 已提交
432

433
	if (request_firmware_direct(&fw, (const char *)fw_name, device)) {
434
		pr_debug("failed to load file %s\n", fw_name);
435
		goto out;
436
	}
D
Dmitry Adamushko 已提交
437

438 439
	ret = UCODE_ERROR;
	if (*(u32 *)fw->data != UCODE_MAGIC) {
440
		pr_err("invalid magic value (0x%08x)\n", *(u32 *)fw->data);
441
		goto fw_release;
442 443
	}

444
	ret = load_microcode_amd(c->x86, fw->data, fw->size);
D
Dmitry Adamushko 已提交
445

446
 fw_release:
447
	release_firmware(fw);
448

449
 out:
D
Dmitry Adamushko 已提交
450 451 452
	return ret;
}

453 454
static enum ucode_state
request_microcode_user(int cpu, const void __user *buf, size_t size)
D
Dmitry Adamushko 已提交
455
{
456
	return UCODE_ERROR;
457 458 459 460 461 462
}

static void microcode_fini_cpu_amd(int cpu)
{
	struct ucode_cpu_info *uci = ucode_cpu_info + cpu;

463
	uci->mc = NULL;
464 465 466
}

static struct microcode_ops microcode_amd_ops = {
D
Dmitry Adamushko 已提交
467
	.request_microcode_user           = request_microcode_user,
468
	.request_microcode_fw             = request_microcode_amd,
469 470 471 472 473
	.collect_cpu_info                 = collect_cpu_info_amd,
	.apply_microcode                  = apply_microcode_amd,
	.microcode_fini_cpu               = microcode_fini_cpu_amd,
};

474
struct microcode_ops * __init init_amd_microcode(void)
475
{
476 477 478 479 480 481 482
	struct cpuinfo_x86 *c = &cpu_data(0);

	if (c->x86_vendor != X86_VENDOR_AMD || c->x86 < 0x10) {
		pr_warning("AMD CPU family 0x%x not supported\n", c->x86);
		return NULL;
	}

483
	return &microcode_amd_ops;
484
}
485 486 487

void __exit exit_amd_microcode(void)
{
488
	cleanup();
489
}