tree: https://git.kernel.org/pub/scm/linux/kernel/git/kvmarm/kvmarm.git kvm-arm64/nv-wip-v5.0-rc1 head: 688c386ca096f2c1f2eee386697586c88df5d5bc commit: 7804bbf602f8d97fc5237ea12cdf28064952085c [43/75] KVM: arm64: nv: Handle shadow stage 2 page faults config: arm-axm55xx_defconfig (attached as .config) compiler: arm-linux-gnueabi-gcc (Debian 7.2.0-11) 7.2.0 reproduce: wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross git checkout 7804bbf602f8d97fc5237ea12cdf28064952085c # save the attached .config to linux build tree GCC_VERSION=7.2.0 make.cross ARCH=arm
All error/warnings (new ones prefixed by >>):
struct kvm *kvm = mmu->kvm;
^~~
arch/arm/kvm/../../../virt/kvm/arm/mmu.c: At top level:
arch/arm/kvm/../../../virt/kvm/arm/mmu.c:1188:35: warning: 'struct
kvm_s2_mmu' declared inside parameter list will not be visible outside of this
definition or declaration
static bool stage2_is_exec(struct kvm_s2_mmu *mmu, phys_addr_t addr)
^~~~~~~~~~
arch/arm/kvm/../../../virt/kvm/arm/mmu.c: In function 'stage2_is_exec':
arch/arm/kvm/../../../virt/kvm/arm/mmu.c:1195:32: error: passing argument 1
of 'stage2_get_leaf_entry' from incompatible pointer type
[-Werror=incompatible-pointer-types]
found = stage2_get_leaf_entry(mmu, addr, &pudp, &pmdp, &ptep);
^~~
arch/arm/kvm/../../../virt/kvm/arm/mmu.c:1150:13: note: expected 'struct
kvm_s2_mmu *' but argument is of type 'struct kvm_s2_mmu *'
static bool stage2_get_leaf_entry(struct kvm_s2_mmu *mmu, phys_addr_t addr,
^~~~~~~~~~~~~~~~~~~~~
arch/arm/kvm/../../../virt/kvm/arm/mmu.c: At top level:
arch/arm/kvm/../../../virt/kvm/arm/mmu.c:1207:34: warning: 'struct
kvm_s2_mmu' declared inside parameter list will not be visible outside of this
definition or declaration
static int stage2_set_pte(struct kvm_s2_mmu *mmu,
^~~~~~~~~~
arch/arm/kvm/../../../virt/kvm/arm/mmu.c: In function 'stage2_set_pte':
arch/arm/kvm/../../../virt/kvm/arm/mmu.c:1212:23: error: dereferencing
pointer to incomplete type 'struct kvm_s2_mmu'
struct kvm *kvm = mmu->kvm;
^~
arch/arm/kvm/../../../virt/kvm/arm/mmu.c:1222:23: error: passing argument 1
of 'stage2_get_pud' from incompatible pointer type
[-Werror=incompatible-pointer-types]
pud = stage2_get_pud(mmu, cache, addr);
^~~
arch/arm/kvm/../../../virt/kvm/arm/mmu.c:1023:15: note: expected 'struct
kvm_s2_mmu *' but argument is of type 'struct kvm_s2_mmu *'
static pud_t *stage2_get_pud(struct kvm_s2_mmu *mmu, struct
kvm_mmu_memory_cache *cache,
^~~~~~~~~~~~~~
arch/arm/kvm/../../../virt/kvm/arm/mmu.c:1236:23: error: passing argument 1
of 'stage2_dissolve_pud' from incompatible pointer type
[-Werror=incompatible-pointer-types]
stage2_dissolve_pud(mmu, addr, pud);
^~~
arch/arm/kvm/../../../virt/kvm/arm/mmu.c:127:13: note: expected 'struct
kvm_s2_mmu *' but argument is of type 'struct kvm_s2_mmu *'
static void stage2_dissolve_pud(struct kvm_s2_mmu *mmu, phys_addr_t addr,
pud_t *pudp)
^~~~~~~~~~~~~~~~~~~
arch/arm/kvm/../../../virt/kvm/arm/mmu.c:1260:23: error: passing argument 1
of 'stage2_dissolve_pmd' from incompatible pointer type
[-Werror=incompatible-pointer-types]
stage2_dissolve_pmd(mmu, addr, pmd);
^~~
arch/arm/kvm/../../../virt/kvm/arm/mmu.c:108:13: note: expected 'struct
kvm_s2_mmu *' but argument is of type 'struct kvm_s2_mmu *'
static void stage2_dissolve_pmd(struct kvm_s2_mmu *mmu, phys_addr_t addr,
pmd_t *pmd)
^~~~~~~~~~~~~~~~~~~
arch/arm/kvm/../../../virt/kvm/arm/mmu.c:1284:26: error: passing argument 1
of 'kvm_tlb_flush_vmid_ipa' from incompatible pointer type
[-Werror=incompatible-pointer-types]
kvm_tlb_flush_vmid_ipa(mmu, addr);
^~~
arch/arm/kvm/../../../virt/kvm/arm/mmu.c:69:13: note: expected 'struct
kvm_s2_mmu *' but argument is of type 'struct kvm_s2_mmu *'
static void kvm_tlb_flush_vmid_ipa(struct kvm_s2_mmu *mmu, phys_addr_t ipa)
^~~~~~~~~~~~~~~~~~~~~~
arch/arm/kvm/../../../virt/kvm/arm/mmu.c:1212:14: warning: unused variable
'kvm' [-Wunused-variable]
struct kvm *kvm = mmu->kvm;
^~~
arch/arm/kvm/../../../virt/kvm/arm/mmu.c: In function
'kvm_phys_addr_ioremap':
arch/arm/kvm/../../../virt/kvm/arm/mmu.c:1350:34: error: 'struct kvm_arch'
has no member named 'mmu'
ret = stage2_set_pte(&kvm->arch.mmu, &cache, addr, &pte,
^
arch/arm/kvm/../../../virt/kvm/arm/mmu.c: At top level:
arch/arm/kvm/../../../virt/kvm/arm/mmu.c:1439:35: warning: 'struct
kvm_s2_mmu' declared inside parameter list will not be visible outside of this
definition or declaration
static void stage2_wp_pmds(struct kvm_s2_mmu *mmu, pud_t *pud,
^~~~~~~~~~
arch/arm/kvm/../../../virt/kvm/arm/mmu.c: In function 'stage2_wp_pmds':
arch/arm/kvm/../../../virt/kvm/arm/mmu.c:1442:23: error: dereferencing
pointer to incomplete type 'struct kvm_s2_mmu'
struct kvm *kvm = mmu->kvm;
^~
arch/arm/kvm/../../../virt/kvm/arm/mmu.c: At top level:
arch/arm/kvm/../../../virt/kvm/arm/mmu.c:1469:36: warning: 'struct
kvm_s2_mmu' declared inside parameter list will not be visible outside of this
definition or declaration
static void stage2_wp_puds(struct kvm_s2_mmu *mmu, pgd_t *pgd,
^~~~~~~~~~
arch/arm/kvm/../../../virt/kvm/arm/mmu.c: In function 'stage2_wp_puds':
arch/arm/kvm/../../../virt/kvm/arm/mmu.c:1472:23: error: dereferencing
pointer to incomplete type 'struct kvm_s2_mmu'
struct kvm *kvm = mmu->kvm;
^~
arch/arm/kvm/../../../virt/kvm/arm/mmu.c:1484:20: error: passing argument 1
of 'stage2_wp_pmds' from incompatible pointer type
[-Werror=incompatible-pointer-types]
stage2_wp_pmds(mmu, pud, addr, next);
^~~
arch/arm/kvm/../../../virt/kvm/arm/mmu.c:1439:13: note: expected 'struct
kvm_s2_mmu *' but argument is of type 'struct kvm_s2_mmu *'
static void stage2_wp_pmds(struct kvm_s2_mmu *mmu, pud_t *pud,
^~~~~~~~~~~~~~
arch/arm/kvm/../../../virt/kvm/arm/mmu.c:1472:14: warning: unused variable
'kvm' [-Wunused-variable]
struct kvm *kvm = mmu->kvm;
^~~
arch/arm/kvm/../../../virt/kvm/arm/mmu.c: At top level:
arch/arm/kvm/../../../virt/kvm/arm/mmu.c:1496:36: warning: 'struct
kvm_s2_mmu' declared inside parameter list will not be visible outside of this
definition or declaration
static void stage2_wp_range(struct kvm_s2_mmu *mmu, phys_addr_t addr,
phys_addr_t end)
^~~~~~~~~~
arch/arm/kvm/../../../virt/kvm/arm/mmu.c: In function 'stage2_wp_range':
arch/arm/kvm/../../../virt/kvm/arm/mmu.c:1498:23: error: dereferencing
pointer to incomplete type 'struct kvm_s2_mmu'
struct kvm *kvm = mmu->kvm;
^~
arch/arm/kvm/../../../virt/kvm/arm/mmu.c:1518:19: error: passing argument 1
of 'stage2_wp_puds' from incompatible pointer type
[-Werror=incompatible-pointer-types]
stage2_wp_puds(mmu, pgd, addr, next);
^~~
arch/arm/kvm/../../../virt/kvm/arm/mmu.c:1469:14: note: expected 'struct
kvm_s2_mmu *' but argument is of type 'struct kvm_s2_mmu *'
static void stage2_wp_puds(struct kvm_s2_mmu *mmu, pgd_t *pgd,
^~~~~~~~~~~~~~
arch/arm/kvm/../../../virt/kvm/arm/mmu.c: In function
'kvm_mmu_wp_memory_region':
arch/arm/kvm/../../../virt/kvm/arm/mmu.c:1543:28: error: 'struct kvm_arch'
has no member named 'mmu'
stage2_wp_range(&kvm->arch.mmu, start, end);
^
arch/arm/kvm/../../../virt/kvm/arm/mmu.c: In function
'kvm_mmu_write_protect_pt_masked':
arch/arm/kvm/../../../virt/kvm/arm/mmu.c:1567:28: error: 'struct kvm_arch'
has no member named 'mmu'
stage2_wp_range(&kvm->arch.mmu, start, end);
^
arch/arm/kvm/../../../virt/kvm/arm/mmu.c: At top level:
>> arch/arm/kvm/../../../virt/kvm/arm/mmu.c:1665:13: warning: 'struct
>> kvm_s2_trans' declared inside parameter list will not be visible outside of
>> this definition or declaration
struct kvm_s2_trans *nested,
^~~~~~~~~~~~
arch/arm/kvm/../../../virt/kvm/arm/mmu.c: In function 'user_mem_abort':
arch/arm/kvm/../../../virt/kvm/arm/mmu.c:1682:37: error: 'struct
kvm_vcpu_arch' has no member named 'hw_mmu'
struct kvm_s2_mmu *mmu = vcpu->arch.hw_mmu;
^
>> arch/arm/kvm/../../../virt/kvm/arm/mmu.c:1709:6: error: implicit declaration
>> of function 'kvm_is_shadow_s2_fault'; did you mean 'kvm_is_write_fault'?
>> [-Werror=implicit-function-declaration]
if (kvm_is_shadow_s2_fault(vcpu)) {
^~~~~~~~~~~~~~~~~~~~~~
kvm_is_write_fault
>> arch/arm/kvm/../../../virt/kvm/arm/mmu.c:1710:15: error: dereferencing
>> pointer to incomplete type 'struct kvm_s2_trans'
ipa = nested->output;
^~
In file included from include/asm-generic/bug.h:18:0,
from arch/arm/include/asm/bug.h:60,
from include/linux/bug.h:5,
from include/linux/mmdebug.h:5,
from include/linux/mm.h:9,
from include/linux/mman.h:5,
from arch/arm/kvm/../../../virt/kvm/arm/mmu.c:19:
include/linux/kernel.h:870:2: error: first argument to
'__builtin_choose_expr' not a constant
__builtin_choose_expr(__safe_cmp(x, y), \
^
include/linux/kernel.h:879:19: note: in expansion of macro '__careful_cmp'
#define min(x, y) __careful_cmp(x, y, <)
^~~~~~~~~~~~~
>> arch/arm/kvm/../../../virt/kvm/arm/mmu.c:1717:18: note: in expansion of
>> macro 'min'
max_map_size = min(nested->block_size, max_map_size);
^~~
arch/arm/kvm/../../../virt/kvm/arm/mmu.c:1810:47: error: passing argument 1
of 'stage2_is_exec' from incompatible pointer type
[-Werror=incompatible-pointer-types]
(fault_status == FSC_PERM && stage2_is_exec(mmu, fault_ipa));
^~~
arch/arm/kvm/../../../virt/kvm/arm/mmu.c:1188:13: note: expected 'struct
kvm_s2_mmu *' but argument is of type 'struct kvm_s2_mmu *'
static bool stage2_is_exec(struct kvm_s2_mmu *mmu, phys_addr_t addr)
^~~~~~~~~~~~~~
arch/arm/kvm/../../../virt/kvm/arm/mmu.c:1822:29: error: passing argument 1
of 'stage2_set_pud_huge' from incompatible pointer type
[-Werror=incompatible-pointer-types]
ret = stage2_set_pud_huge(mmu, memcache, fault_ipa, &new_pud);
^~~
arch/arm/kvm/../../../virt/kvm/arm/mmu.c:1112:12: note: expected 'struct
kvm_s2_mmu *' but argument is of type 'struct kvm_s2_mmu *'
static int stage2_set_pud_huge(struct kvm_s2_mmu *mmu,
^~~~~~~~~~~~~~~~~~~
arch/arm/kvm/../../../virt/kvm/arm/mmu.c:1834:29: error: passing argument 1
of 'stage2_set_pmd_huge' from incompatible pointer type
[-Werror=incompatible-pointer-types]
ret = stage2_set_pmd_huge(mmu, memcache, fault_ipa, &new_pmd);
^~~
arch/arm/kvm/../../../virt/kvm/arm/mmu.c:1064:12: note: expected 'struct
kvm_s2_mmu *' but argument is of type 'struct kvm_s2_mmu *'
static int stage2_set_pmd_huge(struct kvm_s2_mmu *mmu,
^~~~~~~~~~~~~~~~~~~
arch/arm/kvm/../../../virt/kvm/arm/mmu.c:1846:24: error: passing argument 1
of 'stage2_set_pte' from incompatible pointer type
[-Werror=incompatible-pointer-types]
ret = stage2_set_pte(mmu, memcache, fault_ipa, &new_pte, flags);
^~~
arch/arm/kvm/../../../virt/kvm/arm/mmu.c:1207:12: note: expected 'struct
kvm_s2_mmu *' but argument is of type 'struct kvm_s2_mmu *'
static int stage2_set_pte(struct kvm_s2_mmu *mmu,
^~~~~~~~~~~~~~
arch/arm/kvm/../../../virt/kvm/arm/mmu.c: In function 'handle_access_fault':
arch/arm/kvm/../../../virt/kvm/arm/mmu.c:1875:39: error: 'struct
kvm_vcpu_arch' has no member named 'hw_mmu'
if (!stage2_get_leaf_entry(vcpu->arch.hw_mmu, fault_ipa, &pud, &pmd, &pte))
^
arch/arm/kvm/../../../virt/kvm/arm/mmu.c: In function
'kvm_handle_guest_abort':
>> arch/arm/kvm/../../../virt/kvm/arm/mmu.c:1916:22: error: storage size of
>> 'nested_trans' isn't known
struct kvm_s2_trans nested_trans;
^~~~~~~~~~~~
>> arch/arm/kvm/../../../virt/kvm/arm/mmu.c:1975:9: error: implicit declaration
>> of function 'kvm_walk_nested_s2'; did you mean 'kvm_inject_nested_irq'?
>> [-Werror=implicit-function-declaration]
ret = kvm_walk_nested_s2(vcpu, fault_ipa, &nested_trans);
^~~~~~~~~~~~~~~~~~
kvm_inject_nested_irq
>> arch/arm/kvm/../../../virt/kvm/arm/mmu.c:1977:4: error: implicit declaration
>> of function 'kvm_inject_s2_fault'; did you mean 'kvm_inject_pabt'?
>> [-Werror=implicit-function-declaration]
kvm_inject_s2_fault(vcpu, nested_trans.esr);
^~~~~~~~~~~~~~~~~~~
kvm_inject_pabt
arch/arm/kvm/../../../virt/kvm/arm/mmu.c:1916:22: warning: unused variable
'nested_trans' [-Wunused-variable]
struct kvm_s2_trans nested_trans;
^~~~~~~~~~~~
arch/arm/kvm/../../../virt/kvm/arm/mmu.c: In function
'kvm_unmap_hva_handler':
arch/arm/kvm/../../../virt/kvm/arm/mmu.c:2075:35: error: 'struct kvm_arch'
has no member named 'mmu'
kvm_unmap_stage2_range(&kvm->arch.mmu, gpa, size);
^
arch/arm/kvm/../../../virt/kvm/arm/mmu.c: In function 'kvm_unmap_hva_range':
arch/arm/kvm/../../../virt/kvm/arm/mmu.c:2082:16: error: 'struct kvm_arch'
has no member named 'mmu'
if (!kvm->arch.mmu.pgd)
^
arch/arm/kvm/../../../virt/kvm/arm/mmu.c: In function 'kvm_set_spte_handler':
arch/arm/kvm/../../../virt/kvm/arm/mmu.c:2102:27: error: 'struct kvm_arch'
has no member named 'mmu'
stage2_set_pte(&kvm->arch.mmu, NULL, gpa, pte, 0);
^
arch/arm/kvm/../../../virt/kvm/arm/mmu.c: In function 'kvm_set_spte_hva':
arch/arm/kvm/../../../virt/kvm/arm/mmu.c:2113:16: error: 'struct kvm_arch'
has no member named 'mmu'
if (!kvm->arch.mmu.pgd)
^
arch/arm/kvm/../../../virt/kvm/arm/mmu.c: In function 'kvm_age_hva_handler':
arch/arm/kvm/../../../virt/kvm/arm/mmu.c:2136:39: error: 'struct kvm_arch'
has no member named 'mmu'
if (!stage2_get_leaf_entry(&kvm->arch.mmu, gpa, &pud, &pmd, &pte))
^
arch/arm/kvm/../../../virt/kvm/arm/mmu.c: In function
'kvm_test_age_hva_handler':
arch/arm/kvm/../../../virt/kvm/arm/mmu.c:2154:39: error: 'struct kvm_arch'
has no member named 'mmu'
if (!stage2_get_leaf_entry(&kvm->arch.mmu, gpa, &pud, &pmd, &pte))
^
arch/arm/kvm/../../../virt/kvm/arm/mmu.c: In function 'kvm_age_hva':
arch/arm/kvm/../../../virt/kvm/arm/mmu.c:2167:16: error: 'struct kvm_arch'
has no member named 'mmu'
if (!kvm->arch.mmu.pgd)
^
arch/arm/kvm/../../../virt/kvm/arm/mmu.c: In function 'kvm_test_age_hva':
arch/arm/kvm/../../../virt/kvm/arm/mmu.c:2175:16: error: 'struct kvm_arch'
has no member named 'mmu'
if (!kvm->arch.mmu.pgd)
^
arch/arm/kvm/../../../virt/kvm/arm/mmu.c: In function
'kvm_arch_prepare_memory_region':
arch/arm/kvm/../../../virt/kvm/arm/mmu.c:2388:36: error: 'struct kvm_arch'
has no member named 'mmu'
kvm_unmap_stage2_range(&kvm->arch.mmu, mem->guest_phys_addr,
mem->memory_size);
^
arch/arm/kvm/../../../virt/kvm/arm/mmu.c:2390:34: error: 'struct kvm_arch'
has no member named 'mmu'
stage2_flush_memslot(&kvm->arch.mmu, memslot);
^
arch/arm/kvm/../../../virt/kvm/arm/mmu.c: In function
'kvm_arch_flush_shadow_all':
arch/arm/kvm/../../../virt/kvm/arm/mmu.c:2416:27: error: 'struct kvm_arch'
has no member named 'nested_mmus_size'
for (i = 0; i < kvm->arch.nested_mmus_size; i++) {
^
arch/arm/kvm/../../../virt/kvm/arm/mmu.c:2417:38: error: 'struct kvm_arch'
has no member named 'nested_mmus'
struct kvm_s2_mmu *mmu = &kvm->arch.nested_mmus[i];
^
In file included from arch/arm/include/asm/bug.h:60:0,
from include/linux/bug.h:5,
from include/linux/mmdebug.h:5,
from include/linux/mm.h:9,
from include/linux/mman.h:5,
from arch/arm/kvm/../../../virt/kvm/arm/mmu.c:19:
arch/arm/kvm/../../../virt/kvm/arm/mmu.c:2419:14: error: dereferencing
pointer to incomplete type 'struct kvm_s2_mmu'
WARN_ON(mmu->usage_count > 0);
^
include/asm-generic/bug.h:122:25: note: in definition of macro 'WARN_ON'
int __ret_warn_on = !!(condition); \
^~~~~~~~~
arch/arm/kvm/../../../virt/kvm/arm/mmu.c:2422:24: error: passing argument 1
of 'kvm_free_stage2_pgd' from incompatible pointer type
[-Werror=incompatible-pointer-types]
kvm_free_stage2_pgd(mmu);
^~~
arch/arm/kvm/../../../virt/kvm/arm/mmu.c:1005:6: note: expected 'struct
kvm_s2_mmu *' but argument is of type 'struct kvm_s2_mmu *'
void kvm_free_stage2_pgd(struct kvm_s2_mmu *mmu)
^~~~~~~~~~~~~~~~~~~
arch/arm/kvm/../../../virt/kvm/arm/mmu.c:2424:17: error: 'struct kvm_arch'
has no member named 'nested_mmus'
kfree(kvm->arch.nested_mmus);
^
arch/arm/kvm/../../../virt/kvm/arm/mmu.c:2425:11: error: 'struct kvm_arch'
has no member named 'nested_mmus'
kvm->arch.nested_mmus = NULL;
^
arch/arm/kvm/../../../virt/kvm/arm/mmu.c:2426:11: error: 'struct kvm_arch'
has no member named 'nested_mmus_size'
kvm->arch.nested_mmus_size = 0;
^
arch/arm/kvm/../../../virt/kvm/arm/mmu.c:2427:32: error: 'struct kvm_arch'
has no member named 'mmu'
kvm_free_stage2_pgd(&kvm->arch.mmu);
^
arch/arm/kvm/../../../virt/kvm/arm/mmu.c: In function
'kvm_arch_flush_shadow_memslot':
arch/arm/kvm/../../../virt/kvm/arm/mmu.c:2437:35: error: 'struct kvm_arch'
has no member named 'mmu'
kvm_unmap_stage2_range(&kvm->arch.mmu, gpa, size);
^
cc1: some warnings being treated as errors
vim +1709 arch/arm/kvm/../../../virt/kvm/arm/mmu.c
1521
1522 /**
1523 * kvm_mmu_wp_memory_region() - write protect stage 2 entries for
memory slot
1524 * @kvm: The KVM pointer
1525 * @slot: The memory slot to write protect
1526 *
1527 * Called to start logging dirty pages after memory region
1528 * KVM_MEM_LOG_DIRTY_PAGES operation is called. After this function
returns
1529 * all present PUD, PMD and PTEs are write protected in the memory
region.
1530 * Afterwards read of dirty page log can be called.
1531 *
1532 * Acquires kvm_mmu_lock. Called with kvm->slots_lock mutex acquired,
1533 * serializing operations for VM memory regions.
1534 */
1535 void kvm_mmu_wp_memory_region(struct kvm *kvm, int slot)
1536 {
1537 struct kvm_memslots *slots = kvm_memslots(kvm);
1538 struct kvm_memory_slot *memslot = id_to_memslot(slots, slot);
1539 phys_addr_t start = memslot->base_gfn << PAGE_SHIFT;
1540 phys_addr_t end = (memslot->base_gfn + memslot->npages) <<
PAGE_SHIFT;
1541
1542 spin_lock(&kvm->mmu_lock);
> 1543 stage2_wp_range(&kvm->arch.mmu, start, end);
1544 spin_unlock(&kvm->mmu_lock);
1545 kvm_flush_remote_tlbs(kvm);
1546 }
1547
1548 /**
1549 * kvm_mmu_write_protect_pt_masked() - write protect dirty pages
1550 * @kvm: The KVM pointer
1551 * @slot: The memory slot associated with mask
1552 * @gfn_offset: The gfn offset in memory slot
1553 * @mask: The mask of dirty pages at offset 'gfn_offset' in this
memory
1554 * slot to be write protected
1555 *
1556 * Walks bits set in mask write protects the associated pte's. Caller
must
1557 * acquire kvm_mmu_lock.
1558 */
1559 static void kvm_mmu_write_protect_pt_masked(struct kvm *kvm,
1560 struct kvm_memory_slot *slot,
1561 gfn_t gfn_offset, unsigned long mask)
1562 {
1563 phys_addr_t base_gfn = slot->base_gfn + gfn_offset;
1564 phys_addr_t start = (base_gfn + __ffs(mask)) << PAGE_SHIFT;
1565 phys_addr_t end = (base_gfn + __fls(mask) + 1) << PAGE_SHIFT;
1566
1567 stage2_wp_range(&kvm->arch.mmu, start, end);
1568 }
1569
1570 /*
1571 * kvm_arch_mmu_enable_log_dirty_pt_masked - enable dirty logging for
selected
1572 * dirty pages.
1573 *
1574 * It calls kvm_mmu_write_protect_pt_masked to write protect selected
pages to
1575 * enable dirty logging for them.
1576 */
1577 void kvm_arch_mmu_enable_log_dirty_pt_masked(struct kvm *kvm,
1578 struct kvm_memory_slot *slot,
1579 gfn_t gfn_offset, unsigned long mask)
1580 {
1581 kvm_mmu_write_protect_pt_masked(kvm, slot, gfn_offset, mask);
1582 }
1583
1584 static void clean_dcache_guest_page(kvm_pfn_t pfn, unsigned long size)
1585 {
1586 __clean_dcache_guest_page(pfn, size);
1587 }
1588
1589 static void invalidate_icache_guest_page(kvm_pfn_t pfn, unsigned long
size)
1590 {
1591 __invalidate_icache_guest_page(pfn, size);
1592 }
1593
1594 static void kvm_send_hwpoison_signal(unsigned long address,
1595 struct vm_area_struct *vma)
1596 {
1597 short lsb;
1598
1599 if (is_vm_hugetlb_page(vma))
1600 lsb = huge_page_shift(hstate_vma(vma));
1601 else
1602 lsb = PAGE_SHIFT;
1603
1604 send_sig_mceerr(BUS_MCEERR_AR, (void __user *)address, lsb,
current);
1605 }
1606
1607 static bool fault_supports_stage2_pmd_mappings(struct kvm_memory_slot
*memslot,
1608 unsigned long hva)
1609 {
1610 gpa_t gpa_start, gpa_end;
1611 hva_t uaddr_start, uaddr_end;
1612 size_t size;
1613
1614 size = memslot->npages * PAGE_SIZE;
1615
1616 gpa_start = memslot->base_gfn << PAGE_SHIFT;
1617 gpa_end = gpa_start + size;
1618
1619 uaddr_start = memslot->userspace_addr;
1620 uaddr_end = uaddr_start + size;
1621
1622 /*
1623 * Pages belonging to memslots that don't have the same
alignment
1624 * within a PMD for userspace and IPA cannot be mapped with
stage-2
1625 * PMD entries, because we'll end up mapping the wrong pages.
1626 *
1627 * Consider a layout like the following:
1628 *
1629 * memslot->userspace_addr:
1630 * +-----+--------------------+--------------------+---+
1631 * |abcde|fgh Stage-1 PMD | Stage-1 PMD tv|xyz|
1632 * +-----+--------------------+--------------------+---+
1633 *
1634 * memslot->base_gfn << PAGE_SIZE:
1635 * +---+--------------------+--------------------+-----+
1636 * |abc|def Stage-2 PMD | Stage-2 PMD |tvxyz|
1637 * +---+--------------------+--------------------+-----+
1638 *
1639 * If we create those stage-2 PMDs, we'll end up with this
incorrect
1640 * mapping:
1641 * d -> f
1642 * e -> g
1643 * f -> h
1644 */
1645 if ((gpa_start & ~S2_PMD_MASK) != (uaddr_start & ~S2_PMD_MASK))
1646 return false;
1647
1648 /*
1649 * Next, let's make sure we're not trying to map anything not
covered
1650 * by the memslot. This means we have to prohibit PMD size
mappings
1651 * for the beginning and end of a non-PMD aligned and non-PMD
sized
1652 * memory slot (illustrated by the head and tail parts of the
1653 * userspace view above containing pages 'abcde' and 'xyz',
1654 * respectively).
1655 *
1656 * Note that it doesn't matter if we do the check using the
1657 * userspace_addr or the base_gfn, as both are equally aligned
(per
1658 * the check above) and equally sized.
1659 */
1660 return (hva & S2_PMD_MASK) >= uaddr_start &&
1661 (hva & S2_PMD_MASK) + S2_PMD_SIZE <= uaddr_end;
1662 }
1663
1664 static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
> 1665 struct kvm_s2_trans *nested,
1666 struct kvm_memory_slot *memslot,
1667 unsigned long hva, unsigned long fault_status)
1668 {
1669 int ret;
1670 bool write_fault, writable;
1671 bool exec_fault, needs_exec;
1672 unsigned long mmu_seq;
1673 phys_addr_t ipa = fault_ipa;
1674 gfn_t gfn;
1675 struct kvm *kvm = vcpu->kvm;
1676 struct kvm_mmu_memory_cache *memcache =
&vcpu->arch.mmu_page_cache;
1677 struct vm_area_struct *vma;
1678 kvm_pfn_t pfn;
1679 pgprot_t mem_type = PAGE_S2;
1680 bool logging_active = memslot_is_logging(memslot);
1681 unsigned long vma_pagesize, flags = 0;
> 1682 struct kvm_s2_mmu *mmu = vcpu->arch.hw_mmu;
1683 unsigned long max_map_size = PUD_SIZE;
1684
1685 write_fault = kvm_is_write_fault(vcpu);
1686 exec_fault = kvm_vcpu_trap_is_iabt(vcpu);
1687 VM_BUG_ON(write_fault && exec_fault);
1688
1689 if (fault_status == FSC_PERM && !write_fault && !exec_fault) {
1690 kvm_err("Unexpected L2 read permission error\n");
1691 return -EFAULT;
1692 }
1693
1694 if (!fault_supports_stage2_pmd_mappings(memslot, hva))
1695 max_map_size = PAGE_SIZE;
1696
1697 if (logging_active)
1698 max_map_size = PAGE_SIZE;
1699
1700 /* Let's check if we will get back a huge page backed by
hugetlbfs */
1701 down_read(¤t->mm->mmap_sem);
1702 vma = find_vma_intersection(current->mm, hva, hva + 1);
1703 if (unlikely(!vma)) {
1704 kvm_err("Failed to find VMA for hva 0x%lx\n", hva);
1705 up_read(¤t->mm->mmap_sem);
1706 return -EFAULT;
1707 }
1708
> 1709 if (kvm_is_shadow_s2_fault(vcpu)) {
> 1710 ipa = nested->output;
1711
1712 /*
1713 * If we're about to create a shadow stage 2 entry,
then we
1714 * can only create a block mapping if the guest stage 2
page
1715 * table uses at least as big a mapping.
1716 */
> 1717 max_map_size = min(nested->block_size, max_map_size);
1718 }
1719 gfn = ipa >> PAGE_SHIFT;
1720
1721 vma_pagesize = min(vma_kernel_pagesize(vma), max_map_size);
1722 /*
1723 * PUD level may not exist for a VM but PMD is guaranteed to
1724 * exist.
1725 */
1726 if ((vma_pagesize == PMD_SIZE ||
1727 (vma_pagesize == PUD_SIZE && kvm_stage2_has_pud(kvm)))) {
1728 gfn = (ipa & huge_page_mask(hstate_vma(vma))) >>
PAGE_SHIFT;
1729 }
1730 up_read(¤t->mm->mmap_sem);
1731
1732
1733 /* We need minimum second+third level pages */
1734 ret = mmu_topup_memory_cache(memcache,
kvm_mmu_cache_min_pages(kvm),
1735 KVM_NR_MEM_OBJS);
1736 if (ret)
1737 return ret;
1738
1739 mmu_seq = vcpu->kvm->mmu_notifier_seq;
1740 /*
1741 * Ensure the read of mmu_notifier_seq happens before we call
1742 * gfn_to_pfn_prot (which calls get_user_pages), so that we
don't risk
1743 * the page we just got a reference to gets unmapped before we
have a
1744 * chance to grab the mmu_lock, which ensure that if the page
gets
1745 * unmapped afterwards, the call to kvm_unmap_hva will take it
away
1746 * from us again properly. This smp_rmb() interacts with the
smp_wmb()
1747 * in kvm_mmu_notifier_invalidate_<page|range_end>.
1748 */
1749 smp_rmb();
1750
1751 pfn = gfn_to_pfn_prot(kvm, gfn, write_fault, &writable);
1752 if (pfn == KVM_PFN_ERR_HWPOISON) {
1753 kvm_send_hwpoison_signal(hva, vma);
1754 return 0;
1755 }
1756 if (is_error_noslot_pfn(pfn))
1757 return -EFAULT;
1758
1759 if (kvm_is_device_pfn(pfn)) {
1760 mem_type = PAGE_S2_DEVICE;
1761 flags |= KVM_S2PTE_FLAG_IS_IOMAP;
1762 } else if (logging_active) {
1763 /*
1764 * Faults on pages in a memslot with logging enabled
1765 * should not be mapped with huge pages (it introduces
churn
1766 * and performance degradation), so force a pte mapping.
1767 */
1768 flags |= KVM_S2_FLAG_LOGGING_ACTIVE;
1769
1770 /*
1771 * Only actually map the page as writable if this was a
write
1772 * fault.
1773 */
1774 if (!write_fault)
1775 writable = false;
1776 }
1777
1778 spin_lock(&kvm->mmu_lock);
1779 if (mmu_notifier_retry(kvm, mmu_seq))
1780 goto out_unlock;
1781
1782 if (vma_pagesize == PAGE_SIZE && max_map_size >= PMD_SIZE) {
1783 /*
1784 * Only PMD_SIZE transparent hugepages(THP) are
1785 * currently supported. This code will need to be
1786 * updated to support other THP sizes.
1787 */
1788 if (transparent_hugepage_adjust(&pfn, &ipa, &fault_ipa))
1789 vma_pagesize = PMD_SIZE;
1790 }
1791
1792 if (writable)
1793 kvm_set_pfn_dirty(pfn);
1794
1795 if (fault_status != FSC_PERM)
1796 clean_dcache_guest_page(pfn, vma_pagesize);
1797
1798 if (exec_fault)
1799 invalidate_icache_guest_page(pfn, vma_pagesize);
1800
1801 /*
1802 * If we took an execution fault we have made the
1803 * icache/dcache coherent above and should now let the s2
1804 * mapping be executable.
1805 *
1806 * Write faults (!exec_fault && FSC_PERM) are orthogonal to
1807 * execute permissions, and we preserve whatever we have.
1808 */
1809 needs_exec = exec_fault ||
1810 (fault_status == FSC_PERM && stage2_is_exec(mmu,
fault_ipa));
1811
1812 if (vma_pagesize == PUD_SIZE) {
1813 pud_t new_pud = kvm_pfn_pud(pfn, mem_type);
1814
1815 new_pud = kvm_pud_mkhuge(new_pud);
1816 if (writable)
1817 new_pud = kvm_s2pud_mkwrite(new_pud);
1818
1819 if (needs_exec)
1820 new_pud = kvm_s2pud_mkexec(new_pud);
1821
1822 ret = stage2_set_pud_huge(mmu, memcache, fault_ipa,
&new_pud);
1823 } else if (vma_pagesize == PMD_SIZE) {
1824 pmd_t new_pmd = kvm_pfn_pmd(pfn, mem_type);
1825
1826 new_pmd = kvm_pmd_mkhuge(new_pmd);
1827
1828 if (writable)
1829 new_pmd = kvm_s2pmd_mkwrite(new_pmd);
1830
1831 if (needs_exec)
1832 new_pmd = kvm_s2pmd_mkexec(new_pmd);
1833
1834 ret = stage2_set_pmd_huge(mmu, memcache, fault_ipa,
&new_pmd);
1835 } else {
1836 pte_t new_pte = kvm_pfn_pte(pfn, mem_type);
1837
1838 if (writable) {
1839 new_pte = kvm_s2pte_mkwrite(new_pte);
1840 mark_page_dirty(kvm, gfn);
1841 }
1842
1843 if (needs_exec)
1844 new_pte = kvm_s2pte_mkexec(new_pte);
1845
1846 ret = stage2_set_pte(mmu, memcache, fault_ipa,
&new_pte, flags);
1847 }
1848
1849 out_unlock:
1850 spin_unlock(&kvm->mmu_lock);
1851 kvm_set_pfn_accessed(pfn);
1852 kvm_release_pfn_clean(pfn);
1853 return ret;
1854 }
1855
1856 /*
1857 * Resolve the access fault by making the page young again.
1858 * Note that because the faulting entry is guaranteed not to be
1859 * cached in the TLB, we don't need to invalidate anything.
1860 * Only the HW Access Flag updates are supported for Stage 2 (no DBM),
1861 * so there is no need for atomic (pte|pmd)_mkyoung operations.
1862 */
1863 static void handle_access_fault(struct kvm_vcpu *vcpu, phys_addr_t
fault_ipa)
1864 {
1865 pud_t *pud;
1866 pmd_t *pmd;
1867 pte_t *pte;
1868 kvm_pfn_t pfn;
1869 bool pfn_valid = false;
1870
1871 trace_kvm_access_fault(fault_ipa);
1872
1873 spin_lock(&vcpu->kvm->mmu_lock);
1874
> 1875 if (!stage2_get_leaf_entry(vcpu->arch.hw_mmu, fault_ipa, &pud,
> &pmd, &pte))
1876 goto out;
1877
1878 if (pud) { /* HugeTLB */
1879 *pud = kvm_s2pud_mkyoung(*pud);
1880 pfn = kvm_pud_pfn(*pud);
1881 pfn_valid = true;
1882 } else if (pmd) { /* THP, HugeTLB */
1883 *pmd = pmd_mkyoung(*pmd);
1884 pfn = pmd_pfn(*pmd);
1885 pfn_valid = true;
1886 } else {
1887 *pte = pte_mkyoung(*pte); /* Just a page... */
1888 pfn = pte_pfn(*pte);
1889 pfn_valid = true;
1890 }
1891
1892 out:
1893 spin_unlock(&vcpu->kvm->mmu_lock);
1894 if (pfn_valid)
1895 kvm_set_pfn_accessed(pfn);
1896 }
1897
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
.config.gz
Description: application/gzip
_______________________________________________ kvmarm mailing list [email protected] https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
