Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/drivers/cxl/core/mce.c
26282 views
1
// SPDX-License-Identifier: GPL-2.0-only
2
/* Copyright(c) 2024 Intel Corporation. All rights reserved. */
3
#include <linux/mm.h>
4
#include <linux/notifier.h>
5
#include <linux/set_memory.h>
6
#include <asm/mce.h>
7
#include <cxlmem.h>
8
#include "mce.h"
9
10
static int cxl_handle_mce(struct notifier_block *nb, unsigned long val,
11
void *data)
12
{
13
struct cxl_memdev_state *mds = container_of(nb, struct cxl_memdev_state,
14
mce_notifier);
15
struct cxl_memdev *cxlmd = mds->cxlds.cxlmd;
16
struct cxl_port *endpoint = cxlmd->endpoint;
17
struct mce *mce = data;
18
u64 spa, spa_alias;
19
unsigned long pfn;
20
21
if (!mce || !mce_usable_address(mce))
22
return NOTIFY_DONE;
23
24
if (!endpoint)
25
return NOTIFY_DONE;
26
27
spa = mce->addr & MCI_ADDR_PHYSADDR;
28
29
pfn = spa >> PAGE_SHIFT;
30
if (!pfn_valid(pfn))
31
return NOTIFY_DONE;
32
33
spa_alias = cxl_port_get_spa_cache_alias(endpoint, spa);
34
if (spa_alias == ~0ULL)
35
return NOTIFY_DONE;
36
37
pfn = spa_alias >> PAGE_SHIFT;
38
39
/*
40
* Take down the aliased memory page. The original memory page flagged
41
* by the MCE will be taken cared of by the standard MCE handler.
42
*/
43
dev_emerg(mds->cxlds.dev, "Offlining aliased SPA address0: %#llx\n",
44
spa_alias);
45
if (!memory_failure(pfn, 0))
46
set_mce_nospec(pfn);
47
48
return NOTIFY_OK;
49
}
50
51
static void cxl_unregister_mce_notifier(void *mce_notifier)
52
{
53
mce_unregister_decode_chain(mce_notifier);
54
}
55
56
int devm_cxl_register_mce_notifier(struct device *dev,
57
struct notifier_block *mce_notifier)
58
{
59
mce_notifier->notifier_call = cxl_handle_mce;
60
mce_notifier->priority = MCE_PRIO_UC;
61
mce_register_decode_chain(mce_notifier);
62
63
return devm_add_action_or_reset(dev, cxl_unregister_mce_notifier,
64
mce_notifier);
65
}
66
67