* Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "ka_system_pub.h"
#include "ka_memory_pub.h"
#include "ka_sched_pub.h"
#include "svm_kern_log.h"
#include "svm_pgtable.h"
#include "svm_mm.h"
#include "pmq.h"
static int _svm_pmq_query_va(ka_vm_area_struct_t *vma, u64 pa, u64 start_va, u64 end_va, u64 *matched_va)
{
u64 va, tmp_pa, page_size, va_offset, pa_offset;
unsigned long stamp = (unsigned long)ka_jiffies;
for (va = start_va; va < end_va; va += (page_size - va_offset)) {
ka_try_cond_resched(&stamp);
if (svm_va_to_pa(vma, va, &tmp_pa, &page_size) != 0) {
page_size = KA_MM_PAGE_SIZE;
va_offset = va - ka_base_round_down(va, page_size);
continue;
}
va_offset = va - ka_base_round_down(va, page_size);
if ((pa >= tmp_pa) && (pa < (tmp_pa + (page_size - va_offset)))) {
pa_offset = pa - tmp_pa;
*matched_va = va + pa_offset;
return 0;
}
}
return -ESRCH;
}
int svm_pmq_query_va(int tgid, u64 pa, u64 start_va, u64 end_va, u64 *matched_va)
{
ka_vm_area_struct_t *vma = NULL;
ka_mm_struct_t *mm = NULL;
int ret;
mm = svm_mm_get(tgid, false);
if (mm == NULL) {
return -ENOSYS;
}
vma = ka_mm_find_vma(mm, start_va);
if (vma == NULL) {
svm_mm_put(mm, false);
return -EFAULT;
}
ret = _svm_pmq_query_va(vma, pa, start_va, end_va, matched_va);
svm_mm_put(mm, false);
return ret;
}