Commit 58348168 authored by Paolo Bonzini's avatar Paolo Bonzini

Merge tag 'kvmarm-fixes-6.1-1' of...

Merge tag 'kvmarm-fixes-6.1-1' of git://git.kernel.org/pub/scm/linux/kernel/git/kvmarm/kvmarm into HEAD

KVM/arm64 fixes for 6.1, take #1

- Fix for stage-2 invalidation holding the VM MMU lock
  for too long by limiting the walk to the largest
  block mapping size

- Enable stack protection and branch profiling for VHE

- Two selftest fixes
parents 9abf2313 05c2224d
...@@ -13,6 +13,18 @@ ...@@ -13,6 +13,18 @@
#define KVM_PGTABLE_MAX_LEVELS 4U #define KVM_PGTABLE_MAX_LEVELS 4U
/*
* The largest supported block sizes for KVM (no 52-bit PA support):
* - 4K (level 1): 1GB
* - 16K (level 2): 32MB
* - 64K (level 2): 512MB
*/
#ifdef CONFIG_ARM64_4K_PAGES
#define KVM_PGTABLE_MIN_BLOCK_LEVEL 1U
#else
#define KVM_PGTABLE_MIN_BLOCK_LEVEL 2U
#endif
static inline u64 kvm_get_parange(u64 mmfr0) static inline u64 kvm_get_parange(u64 mmfr0)
{ {
u64 parange = cpuid_feature_extract_unsigned_field(mmfr0, u64 parange = cpuid_feature_extract_unsigned_field(mmfr0,
...@@ -58,11 +70,7 @@ static inline u64 kvm_granule_size(u32 level) ...@@ -58,11 +70,7 @@ static inline u64 kvm_granule_size(u32 level)
static inline bool kvm_level_supports_block_mapping(u32 level) static inline bool kvm_level_supports_block_mapping(u32 level)
{ {
/* return level >= KVM_PGTABLE_MIN_BLOCK_LEVEL;
* Reject invalid block mappings and don't bother with 4TB mappings for
* 52-bit PAs.
*/
return !(level == 0 || (PAGE_SIZE != SZ_4K && level == 1));
} }
/** /**
......
...@@ -10,13 +10,6 @@ ...@@ -10,13 +10,6 @@
#include <linux/pgtable.h> #include <linux/pgtable.h>
/*
* PGDIR_SHIFT determines the size a top-level page table entry can map
* and depends on the number of levels in the page table. Compute the
* PGDIR_SHIFT for a given number of levels.
*/
#define pt_levels_pgdir_shift(lvls) ARM64_HW_PGTABLE_LEVEL_SHIFT(4 - (lvls))
/* /*
* The hardware supports concatenation of up to 16 tables at stage2 entry * The hardware supports concatenation of up to 16 tables at stage2 entry
* level and we use the feature whenever possible, which means we resolve 4 * level and we use the feature whenever possible, which means we resolve 4
...@@ -30,11 +23,6 @@ ...@@ -30,11 +23,6 @@
#define stage2_pgtable_levels(ipa) ARM64_HW_PGTABLE_LEVELS((ipa) - 4) #define stage2_pgtable_levels(ipa) ARM64_HW_PGTABLE_LEVELS((ipa) - 4)
#define kvm_stage2_levels(kvm) VTCR_EL2_LVLS(kvm->arch.vtcr) #define kvm_stage2_levels(kvm) VTCR_EL2_LVLS(kvm->arch.vtcr)
/* stage2_pgdir_shift() is the size mapped by top-level stage2 entry for the VM */
#define stage2_pgdir_shift(kvm) pt_levels_pgdir_shift(kvm_stage2_levels(kvm))
#define stage2_pgdir_size(kvm) (1ULL << stage2_pgdir_shift(kvm))
#define stage2_pgdir_mask(kvm) ~(stage2_pgdir_size(kvm) - 1)
/* /*
* kvm_mmmu_cache_min_pages() is the number of pages required to install * kvm_mmmu_cache_min_pages() is the number of pages required to install
* a stage-2 translation. We pre-allocate the entry level page table at * a stage-2 translation. We pre-allocate the entry level page table at
...@@ -42,12 +30,4 @@ ...@@ -42,12 +30,4 @@
*/ */
#define kvm_mmu_cache_min_pages(kvm) (kvm_stage2_levels(kvm) - 1) #define kvm_mmu_cache_min_pages(kvm) (kvm_stage2_levels(kvm) - 1)
static inline phys_addr_t
stage2_pgd_addr_end(struct kvm *kvm, phys_addr_t addr, phys_addr_t end)
{
phys_addr_t boundary = (addr + stage2_pgdir_size(kvm)) & stage2_pgdir_mask(kvm);
return (boundary - 1 < end - 1) ? boundary : end;
}
#endif /* __ARM64_S2_PGTABLE_H_ */ #endif /* __ARM64_S2_PGTABLE_H_ */
...@@ -5,9 +5,6 @@ ...@@ -5,9 +5,6 @@
incdir := $(srctree)/$(src)/include incdir := $(srctree)/$(src)/include
subdir-asflags-y := -I$(incdir) subdir-asflags-y := -I$(incdir)
subdir-ccflags-y := -I$(incdir) \ subdir-ccflags-y := -I$(incdir)
-fno-stack-protector \
-DDISABLE_BRANCH_PROFILING \
$(DISABLE_STACKLEAK_PLUGIN)
obj-$(CONFIG_KVM) += vhe/ nvhe/ pgtable.o obj-$(CONFIG_KVM) += vhe/ nvhe/ pgtable.o
...@@ -10,6 +10,9 @@ asflags-y := -D__KVM_NVHE_HYPERVISOR__ -D__DISABLE_EXPORTS ...@@ -10,6 +10,9 @@ asflags-y := -D__KVM_NVHE_HYPERVISOR__ -D__DISABLE_EXPORTS
# will explode instantly (Words of Marc Zyngier). So introduce a generic flag # will explode instantly (Words of Marc Zyngier). So introduce a generic flag
# __DISABLE_TRACE_MMIO__ to disable MMIO tracing for nVHE KVM. # __DISABLE_TRACE_MMIO__ to disable MMIO tracing for nVHE KVM.
ccflags-y := -D__KVM_NVHE_HYPERVISOR__ -D__DISABLE_EXPORTS -D__DISABLE_TRACE_MMIO__ ccflags-y := -D__KVM_NVHE_HYPERVISOR__ -D__DISABLE_EXPORTS -D__DISABLE_TRACE_MMIO__
ccflags-y += -fno-stack-protector \
-DDISABLE_BRANCH_PROFILING \
$(DISABLE_STACKLEAK_PLUGIN)
hostprogs := gen-hyprel hostprogs := gen-hyprel
HOST_EXTRACFLAGS += -I$(objtree)/include HOST_EXTRACFLAGS += -I$(objtree)/include
......
...@@ -31,6 +31,13 @@ static phys_addr_t hyp_idmap_vector; ...@@ -31,6 +31,13 @@ static phys_addr_t hyp_idmap_vector;
static unsigned long io_map_base; static unsigned long io_map_base;
static phys_addr_t stage2_range_addr_end(phys_addr_t addr, phys_addr_t end)
{
phys_addr_t size = kvm_granule_size(KVM_PGTABLE_MIN_BLOCK_LEVEL);
phys_addr_t boundary = ALIGN_DOWN(addr + size, size);
return (boundary - 1 < end - 1) ? boundary : end;
}
/* /*
* Release kvm_mmu_lock periodically if the memory region is large. Otherwise, * Release kvm_mmu_lock periodically if the memory region is large. Otherwise,
...@@ -52,7 +59,7 @@ static int stage2_apply_range(struct kvm *kvm, phys_addr_t addr, ...@@ -52,7 +59,7 @@ static int stage2_apply_range(struct kvm *kvm, phys_addr_t addr,
if (!pgt) if (!pgt)
return -EINVAL; return -EINVAL;
next = stage2_pgd_addr_end(kvm, addr, end); next = stage2_range_addr_end(addr, end);
ret = fn(pgt, addr, next - addr); ret = fn(pgt, addr, next - addr);
if (ret) if (ret)
break; break;
......
...@@ -662,8 +662,8 @@ int test_kvm_device(uint32_t gic_dev_type) ...@@ -662,8 +662,8 @@ int test_kvm_device(uint32_t gic_dev_type)
: KVM_DEV_TYPE_ARM_VGIC_V2; : KVM_DEV_TYPE_ARM_VGIC_V2;
if (!__kvm_test_create_device(v.vm, other)) { if (!__kvm_test_create_device(v.vm, other)) {
ret = __kvm_test_create_device(v.vm, other); ret = __kvm_create_device(v.vm, other);
TEST_ASSERT(ret && (errno == EINVAL || errno == EEXIST), TEST_ASSERT(ret < 0 && (errno == EINVAL || errno == EEXIST),
"create GIC device while other version exists"); "create GIC device while other version exists");
} }
......
...@@ -67,7 +67,7 @@ struct memslot_antagonist_args { ...@@ -67,7 +67,7 @@ struct memslot_antagonist_args {
static void add_remove_memslot(struct kvm_vm *vm, useconds_t delay, static void add_remove_memslot(struct kvm_vm *vm, useconds_t delay,
uint64_t nr_modifications) uint64_t nr_modifications)
{ {
const uint64_t pages = 1; uint64_t pages = max_t(int, vm->page_size, getpagesize()) / vm->page_size;
uint64_t gpa; uint64_t gpa;
int i; int i;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment