BACKPORT: FROMLIST: KVM: arm64: smmu-v3: Setup event queue
The host can use the event queue for debuging, and unlike the command queue, it would be managed by the kernel. However, it must set in a shared state so it can't be donated to the hypervisor later. This relies on the ARM_SMMU_EVTQ_BASE can't be changed after de-privilege. Link: https://lore.kernel.org/all/20241212180423.1578358-30-smostafa@google.com/ Bug: 357781595 Bug: 384432312 Change-Id: I121ee7931edb890b95278c8e9c25c113d9a06d91 Signed-off-by: Mostafa Saleh <smostafa@google.com>
This commit is contained in:
@@ -342,6 +342,46 @@ static int smmu_init_cmdq(struct hyp_arm_smmu_v3_device *smmu)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Event q support is optional and managed by the kernel,
|
||||
* However, it must set in a shared state so it can't be donated
|
||||
* to the hypervisor later.
|
||||
* This relies on the ARM_SMMU_EVTQ_BASE can't be changed after
|
||||
* de-privilege.
|
||||
*/
|
||||
static int smmu_init_evtq(struct hyp_arm_smmu_v3_device *smmu)
|
||||
{
|
||||
u64 evtq_base, evtq_pfn;
|
||||
size_t evtq_nr_entries, evtq_size, evtq_nr_pages;
|
||||
void *evtq_va, *evtq_end;
|
||||
size_t i;
|
||||
int ret;
|
||||
|
||||
evtq_base = readq_relaxed(smmu->base + ARM_SMMU_EVTQ_BASE);
|
||||
if (!evtq_base)
|
||||
return 0;
|
||||
|
||||
if (evtq_base & ~(Q_BASE_RWA | Q_BASE_ADDR_MASK | Q_BASE_LOG2SIZE))
|
||||
return -EINVAL;
|
||||
|
||||
evtq_nr_entries = 1 << (evtq_base & Q_BASE_LOG2SIZE);
|
||||
evtq_size = evtq_nr_entries * EVTQ_ENT_DWORDS * 8;
|
||||
evtq_nr_pages = PAGE_ALIGN(evtq_size) >> PAGE_SHIFT;
|
||||
|
||||
evtq_pfn = PAGE_ALIGN(evtq_base & Q_BASE_ADDR_MASK) >> PAGE_SHIFT;
|
||||
|
||||
for (i = 0 ; i < evtq_nr_pages ; ++i) {
|
||||
ret = __pkvm_host_share_hyp(evtq_pfn + i);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
evtq_va = hyp_phys_to_virt(evtq_pfn << PAGE_SHIFT);
|
||||
evtq_end = hyp_phys_to_virt((evtq_pfn + evtq_nr_pages) << PAGE_SHIFT);
|
||||
|
||||
return hyp_pin_shared_mem(evtq_va, evtq_end);
|
||||
}
|
||||
|
||||
static int smmu_init_strtab(struct hyp_arm_smmu_v3_device *smmu)
|
||||
{
|
||||
int ret;
|
||||
@@ -429,6 +469,10 @@ static int smmu_init_device(struct hyp_arm_smmu_v3_device *smmu)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = smmu_init_evtq(smmu);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = smmu_init_strtab(smmu);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
Reference in New Issue
Block a user