Skip to content

Commit eff484e

Browse files
eaugerChristoffer Dall
authored andcommitted
KVM: arm64: vgic-its: ITT save and restore
Implement routines to save and restore device ITT and their interrupt table entries (ITE). Signed-off-by: Eric Auger <eric.auger@redhat.com> Reviewed-by: Christoffer Dall <cdall@linaro.org>
1 parent 57a9a11 commit eff484e

File tree

2 files changed

+117
-3
lines changed

2 files changed

+117
-3
lines changed

virt/kvm/arm/vgic/vgic-its.c

Lines changed: 113 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1750,7 +1750,7 @@ static u32 compute_next_devid_offset(struct list_head *h,
17501750
return min_t(u32, next_offset, VITS_DTE_MAX_DEVID_OFFSET);
17511751
}
17521752

1753-
u32 compute_next_eventid_offset(struct list_head *h, struct its_ite *ite)
1753+
static u32 compute_next_eventid_offset(struct list_head *h, struct its_ite *ite)
17541754
{
17551755
struct its_ite *next;
17561756
u32 next_offset;
@@ -1827,14 +1827,124 @@ static int scan_its_table(struct vgic_its *its, gpa_t base, int size, int esz,
18271827
return ret;
18281828
}
18291829

1830+
/**
1831+
* vgic_its_save_ite - Save an interrupt translation entry at @gpa
1832+
*/
1833+
static int vgic_its_save_ite(struct vgic_its *its, struct its_device *dev,
1834+
struct its_ite *ite, gpa_t gpa, int ite_esz)
1835+
{
1836+
struct kvm *kvm = its->dev->kvm;
1837+
u32 next_offset;
1838+
u64 val;
1839+
1840+
next_offset = compute_next_eventid_offset(&dev->itt_head, ite);
1841+
val = ((u64)next_offset << KVM_ITS_ITE_NEXT_SHIFT) |
1842+
((u64)ite->lpi << KVM_ITS_ITE_PINTID_SHIFT) |
1843+
ite->collection->collection_id;
1844+
val = cpu_to_le64(val);
1845+
return kvm_write_guest(kvm, gpa, &val, ite_esz);
1846+
}
1847+
1848+
/**
1849+
* vgic_its_restore_ite - restore an interrupt translation entry
1850+
* @event_id: id used for indexing
1851+
* @ptr: pointer to the ITE entry
1852+
* @opaque: pointer to the its_device
1853+
*/
1854+
static int vgic_its_restore_ite(struct vgic_its *its, u32 event_id,
1855+
void *ptr, void *opaque)
1856+
{
1857+
struct its_device *dev = (struct its_device *)opaque;
1858+
struct its_collection *collection;
1859+
struct kvm *kvm = its->dev->kvm;
1860+
struct kvm_vcpu *vcpu = NULL;
1861+
u64 val;
1862+
u64 *p = (u64 *)ptr;
1863+
struct vgic_irq *irq;
1864+
u32 coll_id, lpi_id;
1865+
struct its_ite *ite;
1866+
u32 offset;
1867+
1868+
val = *p;
1869+
1870+
val = le64_to_cpu(val);
1871+
1872+
coll_id = val & KVM_ITS_ITE_ICID_MASK;
1873+
lpi_id = (val & KVM_ITS_ITE_PINTID_MASK) >> KVM_ITS_ITE_PINTID_SHIFT;
1874+
1875+
if (!lpi_id)
1876+
return 1; /* invalid entry, no choice but to scan next entry */
1877+
1878+
if (lpi_id < VGIC_MIN_LPI)
1879+
return -EINVAL;
1880+
1881+
offset = val >> KVM_ITS_ITE_NEXT_SHIFT;
1882+
if (event_id + offset >= BIT_ULL(dev->num_eventid_bits))
1883+
return -EINVAL;
1884+
1885+
collection = find_collection(its, coll_id);
1886+
if (!collection)
1887+
return -EINVAL;
1888+
1889+
ite = vgic_its_alloc_ite(dev, collection, lpi_id, event_id);
1890+
if (IS_ERR(ite))
1891+
return PTR_ERR(ite);
1892+
1893+
if (its_is_collection_mapped(collection))
1894+
vcpu = kvm_get_vcpu(kvm, collection->target_addr);
1895+
1896+
irq = vgic_add_lpi(kvm, lpi_id, vcpu);
1897+
if (IS_ERR(irq))
1898+
return PTR_ERR(irq);
1899+
ite->irq = irq;
1900+
1901+
return offset;
1902+
}
1903+
1904+
static int vgic_its_ite_cmp(void *priv, struct list_head *a,
1905+
struct list_head *b)
1906+
{
1907+
struct its_ite *itea = container_of(a, struct its_ite, ite_list);
1908+
struct its_ite *iteb = container_of(b, struct its_ite, ite_list);
1909+
1910+
if (itea->event_id < iteb->event_id)
1911+
return -1;
1912+
else
1913+
return 1;
1914+
}
1915+
18301916
static int vgic_its_save_itt(struct vgic_its *its, struct its_device *device)
18311917
{
1832-
return -ENXIO;
1918+
const struct vgic_its_abi *abi = vgic_its_get_abi(its);
1919+
gpa_t base = device->itt_addr;
1920+
struct its_ite *ite;
1921+
int ret;
1922+
int ite_esz = abi->ite_esz;
1923+
1924+
list_sort(NULL, &device->itt_head, vgic_its_ite_cmp);
1925+
1926+
list_for_each_entry(ite, &device->itt_head, ite_list) {
1927+
gpa_t gpa = base + ite->event_id * ite_esz;
1928+
1929+
ret = vgic_its_save_ite(its, device, ite, gpa, ite_esz);
1930+
if (ret)
1931+
return ret;
1932+
}
1933+
return 0;
18331934
}
18341935

18351936
static int vgic_its_restore_itt(struct vgic_its *its, struct its_device *dev)
18361937
{
1837-
return -ENXIO;
1938+
const struct vgic_its_abi *abi = vgic_its_get_abi(its);
1939+
gpa_t base = dev->itt_addr;
1940+
int ret;
1941+
int ite_esz = abi->ite_esz;
1942+
size_t max_size = BIT_ULL(dev->num_eventid_bits) * ite_esz;
1943+
1944+
ret = scan_its_table(its, base, max_size, ite_esz, 0,
1945+
vgic_its_restore_ite, dev);
1946+
1947+
return ret;
18381948
}
18391949

18401950
/**

virt/kvm/arm/vgic/vgic.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,10 @@
8181
#define KVM_ITS_CTE_VALID_MASK BIT_ULL(63)
8282
#define KVM_ITS_CTE_RDBASE_SHIFT 16
8383
#define KVM_ITS_CTE_ICID_MASK GENMASK_ULL(15, 0)
84+
#define KVM_ITS_ITE_NEXT_SHIFT 48
85+
#define KVM_ITS_ITE_PINTID_SHIFT 16
86+
#define KVM_ITS_ITE_PINTID_MASK GENMASK_ULL(47, 16)
87+
#define KVM_ITS_ITE_ICID_MASK GENMASK_ULL(15, 0)
8488
#define KVM_ITS_DTE_VALID_SHIFT 63
8589
#define KVM_ITS_DTE_VALID_MASK BIT_ULL(63)
8690
#define KVM_ITS_DTE_NEXT_SHIFT 49

0 commit comments

Comments
 (0)