Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/powerpc/powernv/opal_hmi.c
39534 views
1
/*-
2
* Copyright (c) 2019 Justin Hibbits
3
*
4
* Redistribution and use in source and binary forms, with or without
5
* modification, are permitted provided that the following conditions
6
* are met:
7
*
8
* 1. Redistributions of source code must retain the above copyright
9
* notice, this list of conditions and the following disclaimer.
10
* 2. Redistributions in binary form must reproduce the above copyright
11
* notice, this list of conditions and the following disclaimer in the
12
* documentation and/or other materials provided with the distribution.
13
*
14
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24
*/
25
26
#include <sys/param.h>
27
#include <sys/types.h>
28
#include <sys/eventhandler.h>
29
#include <sys/kernel.h>
30
#include <sys/systm.h>
31
#include <sys/endian.h>
32
33
#include <vm/vm.h>
34
#include <vm/pmap.h>
35
36
#include <machine/spr.h>
37
#include <machine/trap.h>
38
#include "opal.h"
39
40
struct opal_hmi_event {
41
uint8_t version;
42
uint8_t severity;
43
uint8_t type;
44
uint8_t disposition;
45
uint8_t rsvd_1[4];
46
uint64_t hmer;
47
uint64_t tfmr;
48
union {
49
struct {
50
uint8_t xstop_type;
51
uint8_t rsvd_2[3];
52
uint32_t xstop_reason;
53
union {
54
uint32_t pir;
55
uint32_t chip_id;
56
};
57
};
58
};
59
};
60
61
#define HMI_DISP_RECOVERED 0
62
#define HMI_DISP_NOT_RECOVERED 1
63
64
static void
65
opal_hmi_event_handler(void *unused, struct opal_msg *msg)
66
{
67
struct opal_hmi_event evt;
68
69
memcpy(&evt, &msg->params, sizeof(evt));
70
printf("Hypervisor Maintenance Event received"
71
"(Severity %d, type %d, HMER: %016lx).\n",
72
evt.severity, evt.type, evt.hmer);
73
74
if (evt.disposition == HMI_DISP_NOT_RECOVERED)
75
panic("Unrecoverable hypervisor maintenance exception on CPU %d",
76
evt.pir);
77
78
return;
79
}
80
81
static int
82
opal_hmi_handler2(struct trapframe *frame)
83
{
84
/*
85
* Use DMAP preallocated pcpu memory to handle
86
* the phys flags pointer.
87
*/
88
uint64_t *flags = PCPU_PTR(aim.opal_hmi_flags);
89
int err;
90
91
*flags = 0;
92
err = opal_call(OPAL_HANDLE_HMI2, DMAP_TO_PHYS((vm_offset_t)flags));
93
94
if (be64toh(*flags) & OPAL_HMI_FLAGS_TOD_TB_FAIL)
95
panic("TOD/TB recovery failure");
96
97
if (err == OPAL_SUCCESS)
98
return (0);
99
100
printf("HMI handler failed! OPAL error code: %d\n", err);
101
102
return (-1);
103
}
104
105
static int
106
opal_hmi_handler(struct trapframe *frame)
107
{
108
int err;
109
110
err = opal_call(OPAL_HANDLE_HMI);
111
112
if (err == OPAL_SUCCESS)
113
return (0);
114
115
printf("HMI handler failed! OPAL error code: %d\n", err);
116
117
return (-1);
118
}
119
120
static void
121
opal_setup_hmi(void *data)
122
{
123
/* This only works for OPAL, so first make sure we have it. */
124
if (opal_check() != 0)
125
return;
126
127
if (opal_call(OPAL_CHECK_TOKEN, OPAL_HANDLE_HMI2) == OPAL_TOKEN_PRESENT)
128
hmi_handler = opal_hmi_handler2;
129
else if (opal_call(OPAL_CHECK_TOKEN, OPAL_HANDLE_HMI) == OPAL_TOKEN_PRESENT)
130
hmi_handler = opal_hmi_handler;
131
else {
132
printf("Warning: No OPAL HMI handler found.\n");
133
return;
134
}
135
136
EVENTHANDLER_REGISTER(OPAL_HMI_EVT, opal_hmi_event_handler, NULL,
137
EVENTHANDLER_PRI_ANY);
138
139
if (bootverbose)
140
printf("Installed OPAL HMI handler.\n");
141
}
142
143
SYSINIT(opal_setup_hmi, SI_SUB_CPU, SI_ORDER_ANY, opal_setup_hmi, NULL);
144
145