Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
e6290032
Commit
e6290032
authored
Apr 13, 2021
by
Marc Zyngier
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'kvm-arm64/vlpi-save-restore' into kvmarm-master/next
Signed-off-by:
Marc Zyngier
<
maz@kernel.org
>
parents
c90aad55
8082d50f
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
119 additions
and
12 deletions
+119
-12
Documentation/virt/kvm/devices/arm-vgic-its.rst
Documentation/virt/kvm/devices/arm-vgic-its.rst
+1
-1
arch/arm64/kvm/vgic/vgic-its.c
arch/arm64/kvm/vgic/vgic-its.c
+3
-3
arch/arm64/kvm/vgic/vgic-v3.c
arch/arm64/kvm/vgic/vgic-v3.c
+60
-6
arch/arm64/kvm/vgic/vgic-v4.c
arch/arm64/kvm/vgic/vgic-v4.c
+38
-0
arch/arm64/kvm/vgic/vgic.h
arch/arm64/kvm/vgic/vgic.h
+1
-0
drivers/irqchip/irq-gic-v3-its.c
drivers/irqchip/irq-gic-v3-its.c
+16
-2
No files found.
Documentation/virt/kvm/devices/arm-vgic-its.rst
View file @
e6290032
...
...
@@ -80,7 +80,7 @@ KVM_DEV_ARM_VGIC_GRP_CTRL
-EFAULT Invalid guest ram access
-EBUSY One or more VCPUS are running
-EACCES The virtual ITS is backed by a physical GICv4 ITS, and the
state is not available
state is not available
without GICv4.1
======= ==========================================================
KVM_DEV_ARM_VGIC_GRP_ITS_REGS
...
...
arch/arm64/kvm/vgic/vgic-its.c
View file @
e6290032
...
...
@@ -2218,10 +2218,10 @@ static int vgic_its_save_itt(struct vgic_its *its, struct its_device *device)
/*
* If an LPI carries the HW bit, this means that this
* interrupt is controlled by GICv4, and we do not
* have direct access to that state
. Let's simply fail
* the save operation...
* have direct access to that state
without GICv4.1.
*
Let's simply fail
the save operation...
*/
if
(
ite
->
irq
->
hw
)
if
(
ite
->
irq
->
hw
&&
!
kvm_vgic_global_state
.
has_gicv4_1
)
return
-
EACCES
;
ret
=
vgic_its_save_ite
(
its
,
device
,
ite
,
gpa
,
ite_esz
);
...
...
arch/arm64/kvm/vgic/vgic-v3.c
View file @
e6290032
// SPDX-License-Identifier: GPL-2.0-only
#include <linux/irqchip/arm-gic-v3.h>
#include <linux/irq.h>
#include <linux/irqdomain.h>
#include <linux/kvm.h>
#include <linux/kvm_host.h>
#include <kvm/arm_vgic.h>
...
...
@@ -356,6 +358,32 @@ int vgic_v3_lpi_sync_pending_status(struct kvm *kvm, struct vgic_irq *irq)
return
0
;
}
/*
* The deactivation of the doorbell interrupt will trigger the
* unmapping of the associated vPE.
*/
static
void
unmap_all_vpes
(
struct
vgic_dist
*
dist
)
{
struct
irq_desc
*
desc
;
int
i
;
for
(
i
=
0
;
i
<
dist
->
its_vm
.
nr_vpes
;
i
++
)
{
desc
=
irq_to_desc
(
dist
->
its_vm
.
vpes
[
i
]
->
irq
);
irq_domain_deactivate_irq
(
irq_desc_get_irq_data
(
desc
));
}
}
static
void
map_all_vpes
(
struct
vgic_dist
*
dist
)
{
struct
irq_desc
*
desc
;
int
i
;
for
(
i
=
0
;
i
<
dist
->
its_vm
.
nr_vpes
;
i
++
)
{
desc
=
irq_to_desc
(
dist
->
its_vm
.
vpes
[
i
]
->
irq
);
irq_domain_activate_irq
(
irq_desc_get_irq_data
(
desc
),
false
);
}
}
/**
* vgic_v3_save_pending_tables - Save the pending tables into guest RAM
* kvm lock and all vcpu lock must be held
...
...
@@ -365,13 +393,28 @@ int vgic_v3_save_pending_tables(struct kvm *kvm)
struct
vgic_dist
*
dist
=
&
kvm
->
arch
.
vgic
;
struct
vgic_irq
*
irq
;
gpa_t
last_ptr
=
~
(
gpa_t
)
0
;
int
ret
;
bool
vlpi_avail
=
false
;
int
ret
=
0
;
u8
val
;
if
(
unlikely
(
!
vgic_initialized
(
kvm
)))
return
-
ENXIO
;
/*
* A preparation for getting any VLPI states.
* The above vgic initialized check also ensures that the allocation
* and enabling of the doorbells have already been done.
*/
if
(
kvm_vgic_global_state
.
has_gicv4_1
)
{
unmap_all_vpes
(
dist
);
vlpi_avail
=
true
;
}
list_for_each_entry
(
irq
,
&
dist
->
lpi_list_head
,
lpi_list
)
{
int
byte_offset
,
bit_nr
;
struct
kvm_vcpu
*
vcpu
;
gpa_t
pendbase
,
ptr
;
bool
is_pending
;
bool
stored
;
vcpu
=
irq
->
target_vcpu
;
...
...
@@ -387,24 +430,35 @@ int vgic_v3_save_pending_tables(struct kvm *kvm)
if
(
ptr
!=
last_ptr
)
{
ret
=
kvm_read_guest_lock
(
kvm
,
ptr
,
&
val
,
1
);
if
(
ret
)
return
re
t
;
goto
ou
t
;
last_ptr
=
ptr
;
}
stored
=
val
&
(
1U
<<
bit_nr
);
if
(
stored
==
irq
->
pending_latch
)
is_pending
=
irq
->
pending_latch
;
if
(
irq
->
hw
&&
vlpi_avail
)
vgic_v4_get_vlpi_state
(
irq
,
&
is_pending
);
if
(
stored
==
is_pending
)
continue
;
if
(
i
rq
->
pending_latch
)
if
(
i
s_pending
)
val
|=
1
<<
bit_nr
;
else
val
&=
~
(
1
<<
bit_nr
);
ret
=
kvm_write_guest_lock
(
kvm
,
ptr
,
&
val
,
1
);
if
(
ret
)
return
re
t
;
goto
ou
t
;
}
return
0
;
out:
if
(
vlpi_avail
)
map_all_vpes
(
dist
);
return
ret
;
}
/**
...
...
arch/arm64/kvm/vgic/vgic-v4.c
View file @
e6290032
...
...
@@ -203,6 +203,25 @@ void vgic_v4_configure_vsgis(struct kvm *kvm)
kvm_arm_resume_guest
(
kvm
);
}
/*
* Must be called with GICv4.1 and the vPE unmapped, which
* indicates the invalidation of any VPT caches associated
* with the vPE, thus we can get the VLPI state by peeking
* at the VPT.
*/
void
vgic_v4_get_vlpi_state
(
struct
vgic_irq
*
irq
,
bool
*
val
)
{
struct
its_vpe
*
vpe
=
&
irq
->
target_vcpu
->
arch
.
vgic_cpu
.
vgic_v3
.
its_vpe
;
int
mask
=
BIT
(
irq
->
intid
%
BITS_PER_BYTE
);
void
*
va
;
u8
*
ptr
;
va
=
page_address
(
vpe
->
vpt_page
);
ptr
=
va
+
irq
->
intid
/
BITS_PER_BYTE
;
*
val
=
!!
(
*
ptr
&
mask
);
}
/**
* vgic_v4_init - Initialize the GICv4 data structures
* @kvm: Pointer to the VM being initialized
...
...
@@ -385,6 +404,7 @@ int kvm_vgic_v4_set_forwarding(struct kvm *kvm, int virq,
struct
vgic_its
*
its
;
struct
vgic_irq
*
irq
;
struct
its_vlpi_map
map
;
unsigned
long
flags
;
int
ret
;
if
(
!
vgic_supports_direct_msis
(
kvm
))
...
...
@@ -430,6 +450,24 @@ int kvm_vgic_v4_set_forwarding(struct kvm *kvm, int virq,
irq
->
host_irq
=
virq
;
atomic_inc
(
&
map
.
vpe
->
vlpi_count
);
/* Transfer pending state */
raw_spin_lock_irqsave
(
&
irq
->
irq_lock
,
flags
);
if
(
irq
->
pending_latch
)
{
ret
=
irq_set_irqchip_state
(
irq
->
host_irq
,
IRQCHIP_STATE_PENDING
,
irq
->
pending_latch
);
WARN_RATELIMIT
(
ret
,
"IRQ %d"
,
irq
->
host_irq
);
/*
* Clear pending_latch and communicate this state
* change via vgic_queue_irq_unlock.
*/
irq
->
pending_latch
=
false
;
vgic_queue_irq_unlock
(
kvm
,
irq
,
flags
);
}
else
{
raw_spin_unlock_irqrestore
(
&
irq
->
irq_lock
,
flags
);
}
out:
mutex_unlock
(
&
its
->
its_lock
);
return
ret
;
...
...
arch/arm64/kvm/vgic/vgic.h
View file @
e6290032
...
...
@@ -318,5 +318,6 @@ bool vgic_supports_direct_msis(struct kvm *kvm);
int
vgic_v4_init
(
struct
kvm
*
kvm
);
void
vgic_v4_teardown
(
struct
kvm
*
kvm
);
void
vgic_v4_configure_vsgis
(
struct
kvm
*
kvm
);
void
vgic_v4_get_vlpi_state
(
struct
vgic_irq
*
irq
,
bool
*
val
);
#endif
drivers/irqchip/irq-gic-v3-its.c
View file @
e6290032
...
...
@@ -794,8 +794,13 @@ static struct its_vpe *its_build_vmapp_cmd(struct its_node *its,
its_encode_alloc
(
cmd
,
alloc
);
/* We can only signal PTZ when alloc==1. Why do we have two bits? */
its_encode_ptz
(
cmd
,
alloc
);
/*
* GICv4.1 provides a way to get the VLPI state, which needs the vPE
* to be unmapped first, and in this case, we may remap the vPE
* back while the VPT is not empty. So we can't assume that the
* VPT is empty on map. This is why we never advertise PTZ.
*/
its_encode_ptz
(
cmd
,
false
);
its_encode_vconf_addr
(
cmd
,
vconf_addr
);
its_encode_vmapp_default_db
(
cmd
,
desc
->
its_vmapp_cmd
.
vpe
->
vpe_db_lpi
);
...
...
@@ -4554,6 +4559,15 @@ static void its_vpe_irq_domain_deactivate(struct irq_domain *domain,
its_send_vmapp
(
its
,
vpe
,
false
);
}
/*
* There may be a direct read to the VPT after unmapping the
* vPE, to guarantee the validity of this, we make the VPT
* memory coherent with the CPU caches here.
*/
if
(
find_4_1_its
()
&&
!
atomic_read
(
&
vpe
->
vmapp_count
))
gic_flush_dcache_to_poc
(
page_address
(
vpe
->
vpt_page
),
LPI_PENDBASE_SZ
);
}
static
const
struct
irq_domain_ops
its_vpe_domain_ops
=
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment