Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/powerpc/kvm/book3s_xics.h
26451 views
1
/* SPDX-License-Identifier: GPL-2.0-only */
2
/*
3
* Copyright 2012 Michael Ellerman, IBM Corporation.
4
* Copyright 2012 Benjamin Herrenschmidt, IBM Corporation
5
*/
6
7
#ifndef _KVM_PPC_BOOK3S_XICS_H
8
#define _KVM_PPC_BOOK3S_XICS_H
9
10
#ifdef CONFIG_KVM_XICS
11
/*
12
* We use a two-level tree to store interrupt source information.
13
* There are up to 1024 ICS nodes, each of which can represent
14
* 1024 sources.
15
*/
16
#define KVMPPC_XICS_MAX_ICS_ID 1023
17
#define KVMPPC_XICS_ICS_SHIFT 10
18
#define KVMPPC_XICS_IRQ_PER_ICS (1 << KVMPPC_XICS_ICS_SHIFT)
19
#define KVMPPC_XICS_SRC_MASK (KVMPPC_XICS_IRQ_PER_ICS - 1)
20
21
/*
22
* Interrupt source numbers below this are reserved, for example
23
* 0 is "no interrupt", and 2 is used for IPIs.
24
*/
25
#define KVMPPC_XICS_FIRST_IRQ 16
26
#define KVMPPC_XICS_NR_IRQS ((KVMPPC_XICS_MAX_ICS_ID + 1) * \
27
KVMPPC_XICS_IRQ_PER_ICS)
28
29
/* Priority value to use for disabling an interrupt */
30
#define MASKED 0xff
31
32
#define PQ_PRESENTED 1
33
#define PQ_QUEUED 2
34
35
/* State for one irq source */
36
struct ics_irq_state {
37
u32 number;
38
u32 server;
39
u32 pq_state;
40
u8 priority;
41
u8 saved_priority;
42
u8 resend;
43
u8 masked_pending;
44
u8 lsi; /* level-sensitive interrupt */
45
u8 exists;
46
int intr_cpu;
47
u32 host_irq;
48
};
49
50
/* Atomic ICP state, updated with a single compare & swap */
51
union kvmppc_icp_state {
52
unsigned long raw;
53
struct {
54
u8 out_ee:1;
55
u8 need_resend:1;
56
u8 cppr;
57
u8 mfrr;
58
u8 pending_pri;
59
u32 xisr;
60
};
61
};
62
63
/* One bit per ICS */
64
#define ICP_RESEND_MAP_SIZE (KVMPPC_XICS_MAX_ICS_ID / BITS_PER_LONG + 1)
65
66
struct kvmppc_icp {
67
struct kvm_vcpu *vcpu;
68
unsigned long server_num;
69
union kvmppc_icp_state state;
70
unsigned long resend_map[ICP_RESEND_MAP_SIZE];
71
72
/* Real mode might find something too hard, here's the action
73
* it might request from virtual mode
74
*/
75
#define XICS_RM_KICK_VCPU 0x1
76
#define XICS_RM_CHECK_RESEND 0x2
77
#define XICS_RM_NOTIFY_EOI 0x8
78
u32 rm_action;
79
struct kvm_vcpu *rm_kick_target;
80
struct kvmppc_icp *rm_resend_icp;
81
u32 rm_reject;
82
u32 rm_eoied_irq;
83
84
/* Counters for each reason we exited real mode */
85
unsigned long n_rm_kick_vcpu;
86
unsigned long n_rm_check_resend;
87
unsigned long n_rm_notify_eoi;
88
/* Counters for handling ICP processing in real mode */
89
unsigned long n_check_resend;
90
unsigned long n_reject;
91
92
/* Debug stuff for real mode */
93
union kvmppc_icp_state rm_dbgstate;
94
struct kvm_vcpu *rm_dbgtgt;
95
};
96
97
struct kvmppc_ics {
98
arch_spinlock_t lock;
99
u16 icsid;
100
struct ics_irq_state irq_state[KVMPPC_XICS_IRQ_PER_ICS];
101
};
102
103
struct kvmppc_xics {
104
struct kvm *kvm;
105
struct kvm_device *dev;
106
struct dentry *dentry;
107
u32 max_icsid;
108
bool real_mode;
109
bool real_mode_dbg;
110
u32 err_noics;
111
u32 err_noicp;
112
struct kvmppc_ics *ics[KVMPPC_XICS_MAX_ICS_ID + 1];
113
};
114
115
static inline struct kvmppc_icp *kvmppc_xics_find_server(struct kvm *kvm,
116
u32 nr)
117
{
118
struct kvm_vcpu *vcpu = NULL;
119
unsigned long i;
120
121
kvm_for_each_vcpu(i, vcpu, kvm) {
122
if (vcpu->arch.icp && nr == vcpu->arch.icp->server_num)
123
return vcpu->arch.icp;
124
}
125
return NULL;
126
}
127
128
static inline struct kvmppc_ics *kvmppc_xics_find_ics(struct kvmppc_xics *xics,
129
u32 irq, u16 *source)
130
{
131
u32 icsid = irq >> KVMPPC_XICS_ICS_SHIFT;
132
u16 src = irq & KVMPPC_XICS_SRC_MASK;
133
struct kvmppc_ics *ics;
134
135
if (source)
136
*source = src;
137
if (icsid > KVMPPC_XICS_MAX_ICS_ID)
138
return NULL;
139
ics = xics->ics[icsid];
140
if (!ics)
141
return NULL;
142
return ics;
143
}
144
145
extern unsigned long xics_rm_h_xirr(struct kvm_vcpu *vcpu);
146
extern unsigned long xics_rm_h_xirr_x(struct kvm_vcpu *vcpu);
147
extern int xics_rm_h_ipi(struct kvm_vcpu *vcpu, unsigned long server,
148
unsigned long mfrr);
149
extern int xics_rm_h_cppr(struct kvm_vcpu *vcpu, unsigned long cppr);
150
extern int xics_rm_h_eoi(struct kvm_vcpu *vcpu, unsigned long xirr);
151
152
#endif /* CONFIG_KVM_XICS */
153
#endif /* _KVM_PPC_BOOK3S_XICS_H */
154
155