cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

errata.c (2131B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Copyright (C) 2021 Heiko Stuebner <heiko@sntech.de>
      4 */
      5
      6#include <linux/bug.h>
      7#include <linux/kernel.h>
      8#include <linux/module.h>
      9#include <linux/string.h>
     10#include <linux/uaccess.h>
     11#include <asm/alternative.h>
     12#include <asm/cacheflush.h>
     13#include <asm/errata_list.h>
     14#include <asm/patch.h>
     15#include <asm/vendorid_list.h>
     16
     17struct errata_info {
     18	char name[ERRATA_STRING_LENGTH_MAX];
     19	bool (*check_func)(unsigned long arch_id, unsigned long impid);
     20	unsigned int stage;
     21};
     22
     23static bool errata_mt_check_func(unsigned long  arch_id, unsigned long impid)
     24{
     25	if (arch_id != 0 || impid != 0)
     26		return false;
     27	return true;
     28}
     29
     30static const struct errata_info errata_list[ERRATA_THEAD_NUMBER] = {
     31	{
     32		.name = "memory-types",
     33		.stage = RISCV_ALTERNATIVES_EARLY_BOOT,
     34		.check_func = errata_mt_check_func
     35	},
     36};
     37
     38static u32 thead_errata_probe(unsigned int stage, unsigned long archid, unsigned long impid)
     39{
     40	const struct errata_info *info;
     41	u32 cpu_req_errata = 0;
     42	int idx;
     43
     44	for (idx = 0; idx < ERRATA_THEAD_NUMBER; idx++) {
     45		info = &errata_list[idx];
     46
     47		if ((stage == RISCV_ALTERNATIVES_MODULE ||
     48		     info->stage == stage) && info->check_func(archid, impid))
     49			cpu_req_errata |= (1U << idx);
     50	}
     51
     52	return cpu_req_errata;
     53}
     54
     55void __init_or_module thead_errata_patch_func(struct alt_entry *begin, struct alt_entry *end,
     56					      unsigned long archid, unsigned long impid,
     57					      unsigned int stage)
     58{
     59	struct alt_entry *alt;
     60	u32 cpu_req_errata = thead_errata_probe(stage, archid, impid);
     61	u32 tmp;
     62
     63	for (alt = begin; alt < end; alt++) {
     64		if (alt->vendor_id != THEAD_VENDOR_ID)
     65			continue;
     66		if (alt->errata_id >= ERRATA_THEAD_NUMBER)
     67			continue;
     68
     69		tmp = (1U << alt->errata_id);
     70		if (cpu_req_errata & tmp) {
     71			/* On vm-alternatives, the mmu isn't running yet */
     72			if (stage == RISCV_ALTERNATIVES_EARLY_BOOT)
     73				memcpy((void *)__pa_symbol(alt->old_ptr),
     74				       (void *)__pa_symbol(alt->alt_ptr), alt->alt_len);
     75			else
     76				patch_text_nosync(alt->old_ptr, alt->alt_ptr, alt->alt_len);
     77		}
     78	}
     79
     80	if (stage == RISCV_ALTERNATIVES_EARLY_BOOT)
     81		local_flush_icache_all();
     82}