You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm
Pull KVM updates from Paolo Bonzini:
"Small release, the most interesting stuff is x86 nested virt
improvements.
x86:
- userspace can now hide nested VMX features from guests
- nested VMX can now run Hyper-V in a guest
- support for AVX512_4VNNIW and AVX512_FMAPS in KVM
- infrastructure support for virtual Intel GPUs.
PPC:
- support for KVM guests on POWER9
- improved support for interrupt polling
- optimizations and cleanups.
s390:
- two small optimizations, more stuff is in flight and will be in
4.11.
ARM:
- support for the GICv3 ITS on 32bit platforms"
* tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm: (94 commits)
arm64: KVM: pmu: Reset PMSELR_EL0.SEL to a sane value before entering the guest
KVM: arm/arm64: timer: Check for properly initialized timer on init
KVM: arm/arm64: vgic-v2: Limit ITARGETSR bits to number of VCPUs
KVM: x86: Handle the kthread worker using the new API
KVM: nVMX: invvpid handling improvements
KVM: nVMX: check host CR3 on vmentry and vmexit
KVM: nVMX: introduce nested_vmx_load_cr3 and call it on vmentry
KVM: nVMX: propagate errors from prepare_vmcs02
KVM: nVMX: fix CR3 load if L2 uses PAE paging and EPT
KVM: nVMX: load GUEST_EFER after GUEST_CR0 during emulated VM-entry
KVM: nVMX: generate MSR_IA32_CR{0,4}_FIXED1 from guest CPUID
KVM: nVMX: fix checks on CR{0,4} during virtual VMX operation
KVM: nVMX: support restore of VMX capability MSRs
KVM: nVMX: generate non-true VMX MSRs based on true versions
KVM: x86: Do not clear RFLAGS.TF when a singlestep trap occurs.
KVM: x86: Add kvm_skip_emulated_instruction and use it.
KVM: VMX: Move skip_emulated_instruction out of nested_vmx_check_vmcs12
KVM: VMX: Reorder some skip_emulated_instruction calls
KVM: x86: Add a return value to kvm_emulate_cpuid
KVM: PPC: Book3S: Move prototypes for KVM functions into kvm_ppc.h
...
This commit is contained in:
@@ -425,6 +425,11 @@ int kvm_timer_hyp_init(void)
|
||||
info = arch_timer_get_kvm_info();
|
||||
timecounter = &info->timecounter;
|
||||
|
||||
if (!timecounter->cc) {
|
||||
kvm_err("kvm_arch_timer: uninitialized timecounter\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (info->virtual_irq <= 0) {
|
||||
kvm_err("kvm_arch_timer: invalid virtual timer IRQ: %d\n",
|
||||
info->virtual_irq);
|
||||
@@ -498,17 +503,7 @@ int kvm_timer_enable(struct kvm_vcpu *vcpu)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
||||
/*
|
||||
* There is a potential race here between VCPUs starting for the first
|
||||
* time, which may be enabling the timer multiple times. That doesn't
|
||||
* hurt though, because we're just setting a variable to the same
|
||||
* variable that it already was. The important thing is that all
|
||||
* VCPUs have the enabled variable set, before entering the guest, if
|
||||
* the arch timers are enabled.
|
||||
*/
|
||||
if (timecounter)
|
||||
timer->enabled = 1;
|
||||
timer->enabled = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -632,21 +632,22 @@ static bool vgic_its_check_id(struct vgic_its *its, u64 baser, int id)
|
||||
int index;
|
||||
u64 indirect_ptr;
|
||||
gfn_t gfn;
|
||||
int esz = GITS_BASER_ENTRY_SIZE(baser);
|
||||
|
||||
if (!(baser & GITS_BASER_INDIRECT)) {
|
||||
phys_addr_t addr;
|
||||
|
||||
if (id >= (l1_tbl_size / GITS_BASER_ENTRY_SIZE(baser)))
|
||||
if (id >= (l1_tbl_size / esz))
|
||||
return false;
|
||||
|
||||
addr = BASER_ADDRESS(baser) + id * GITS_BASER_ENTRY_SIZE(baser);
|
||||
addr = BASER_ADDRESS(baser) + id * esz;
|
||||
gfn = addr >> PAGE_SHIFT;
|
||||
|
||||
return kvm_is_visible_gfn(its->dev->kvm, gfn);
|
||||
}
|
||||
|
||||
/* calculate and check the index into the 1st level */
|
||||
index = id / (SZ_64K / GITS_BASER_ENTRY_SIZE(baser));
|
||||
index = id / (SZ_64K / esz);
|
||||
if (index >= (l1_tbl_size / sizeof(u64)))
|
||||
return false;
|
||||
|
||||
@@ -670,8 +671,8 @@ static bool vgic_its_check_id(struct vgic_its *its, u64 baser, int id)
|
||||
indirect_ptr &= GENMASK_ULL(51, 16);
|
||||
|
||||
/* Find the address of the actual entry */
|
||||
index = id % (SZ_64K / GITS_BASER_ENTRY_SIZE(baser));
|
||||
indirect_ptr += index * GITS_BASER_ENTRY_SIZE(baser);
|
||||
index = id % (SZ_64K / esz);
|
||||
indirect_ptr += index * esz;
|
||||
gfn = indirect_ptr >> PAGE_SHIFT;
|
||||
|
||||
return kvm_is_visible_gfn(its->dev->kvm, gfn);
|
||||
|
||||
@@ -221,11 +221,9 @@ int kvm_register_vgic_device(unsigned long type)
|
||||
ret = kvm_register_device_ops(&kvm_arm_vgic_v3_ops,
|
||||
KVM_DEV_TYPE_ARM_VGIC_V3);
|
||||
|
||||
#ifdef CONFIG_KVM_ARM_VGIC_V3_ITS
|
||||
if (ret)
|
||||
break;
|
||||
ret = kvm_vgic_register_its_device();
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -129,6 +129,7 @@ static void vgic_mmio_write_target(struct kvm_vcpu *vcpu,
|
||||
unsigned long val)
|
||||
{
|
||||
u32 intid = VGIC_ADDR_TO_INTID(addr, 8);
|
||||
u8 cpu_mask = GENMASK(atomic_read(&vcpu->kvm->online_vcpus) - 1, 0);
|
||||
int i;
|
||||
|
||||
/* GICD_ITARGETSR[0-7] are read-only */
|
||||
@@ -141,7 +142,7 @@ static void vgic_mmio_write_target(struct kvm_vcpu *vcpu,
|
||||
|
||||
spin_lock(&irq->irq_lock);
|
||||
|
||||
irq->targets = (val >> (i * 8)) & 0xff;
|
||||
irq->targets = (val >> (i * 8)) & cpu_mask;
|
||||
target = irq->targets ? __ffs(irq->targets) : 0;
|
||||
irq->target_vcpu = kvm_get_vcpu(vcpu->kvm, target);
|
||||
|
||||
|
||||
@@ -42,7 +42,6 @@ u64 update_64bit_reg(u64 reg, unsigned int offset, unsigned int len,
|
||||
return reg | ((u64)val << lower);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_KVM_ARM_VGIC_V3_ITS
|
||||
bool vgic_has_its(struct kvm *kvm)
|
||||
{
|
||||
struct vgic_dist *dist = &kvm->arch.vgic;
|
||||
@@ -52,7 +51,6 @@ bool vgic_has_its(struct kvm *kvm)
|
||||
|
||||
return dist->has_its;
|
||||
}
|
||||
#endif
|
||||
|
||||
static unsigned long vgic_mmio_read_v3_misc(struct kvm_vcpu *vcpu,
|
||||
gpa_t addr, unsigned int len)
|
||||
|
||||
@@ -84,37 +84,11 @@ int vgic_v3_probe(const struct gic_kvm_info *info);
|
||||
int vgic_v3_map_resources(struct kvm *kvm);
|
||||
int vgic_register_redist_iodevs(struct kvm *kvm, gpa_t dist_base_address);
|
||||
|
||||
#ifdef CONFIG_KVM_ARM_VGIC_V3_ITS
|
||||
int vgic_register_its_iodevs(struct kvm *kvm);
|
||||
bool vgic_has_its(struct kvm *kvm);
|
||||
int kvm_vgic_register_its_device(void);
|
||||
void vgic_enable_lpis(struct kvm_vcpu *vcpu);
|
||||
int vgic_its_inject_msi(struct kvm *kvm, struct kvm_msi *msi);
|
||||
#else
|
||||
static inline int vgic_register_its_iodevs(struct kvm *kvm)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static inline bool vgic_has_its(struct kvm *kvm)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline int kvm_vgic_register_its_device(void)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static inline void vgic_enable_lpis(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
}
|
||||
|
||||
static inline int vgic_its_inject_msi(struct kvm *kvm, struct kvm_msi *msi)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
#endif
|
||||
|
||||
int kvm_register_vgic_device(unsigned long type);
|
||||
int vgic_lazy_init(struct kvm *kvm);
|
||||
|
||||
+78
-9
@@ -70,16 +70,19 @@ MODULE_AUTHOR("Qumranet");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
/* Architectures should define their poll value according to the halt latency */
|
||||
static unsigned int halt_poll_ns = KVM_HALT_POLL_NS_DEFAULT;
|
||||
unsigned int halt_poll_ns = KVM_HALT_POLL_NS_DEFAULT;
|
||||
module_param(halt_poll_ns, uint, S_IRUGO | S_IWUSR);
|
||||
EXPORT_SYMBOL_GPL(halt_poll_ns);
|
||||
|
||||
/* Default doubles per-vcpu halt_poll_ns. */
|
||||
static unsigned int halt_poll_ns_grow = 2;
|
||||
unsigned int halt_poll_ns_grow = 2;
|
||||
module_param(halt_poll_ns_grow, uint, S_IRUGO | S_IWUSR);
|
||||
EXPORT_SYMBOL_GPL(halt_poll_ns_grow);
|
||||
|
||||
/* Default resets per-vcpu halt_poll_ns . */
|
||||
static unsigned int halt_poll_ns_shrink;
|
||||
unsigned int halt_poll_ns_shrink;
|
||||
module_param(halt_poll_ns_shrink, uint, S_IRUGO | S_IWUSR);
|
||||
EXPORT_SYMBOL_GPL(halt_poll_ns_shrink);
|
||||
|
||||
/*
|
||||
* Ordering of locks:
|
||||
@@ -595,7 +598,7 @@ static int kvm_create_vm_debugfs(struct kvm *kvm, int fd)
|
||||
stat_data->kvm = kvm;
|
||||
stat_data->offset = p->offset;
|
||||
kvm->debugfs_stat_data[p - debugfs_entries] = stat_data;
|
||||
if (!debugfs_create_file(p->name, 0444,
|
||||
if (!debugfs_create_file(p->name, 0644,
|
||||
kvm->debugfs_dentry,
|
||||
stat_data,
|
||||
stat_fops_per_vm[p->kind]))
|
||||
@@ -3669,11 +3672,23 @@ static int vm_stat_get_per_vm(void *data, u64 *val)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vm_stat_clear_per_vm(void *data, u64 val)
|
||||
{
|
||||
struct kvm_stat_data *stat_data = (struct kvm_stat_data *)data;
|
||||
|
||||
if (val)
|
||||
return -EINVAL;
|
||||
|
||||
*(ulong *)((void *)stat_data->kvm + stat_data->offset) = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vm_stat_get_per_vm_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
__simple_attr_check_format("%llu\n", 0ull);
|
||||
return kvm_debugfs_open(inode, file, vm_stat_get_per_vm,
|
||||
NULL, "%llu\n");
|
||||
vm_stat_clear_per_vm, "%llu\n");
|
||||
}
|
||||
|
||||
static const struct file_operations vm_stat_get_per_vm_fops = {
|
||||
@@ -3699,11 +3714,26 @@ static int vcpu_stat_get_per_vm(void *data, u64 *val)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vcpu_stat_clear_per_vm(void *data, u64 val)
|
||||
{
|
||||
int i;
|
||||
struct kvm_stat_data *stat_data = (struct kvm_stat_data *)data;
|
||||
struct kvm_vcpu *vcpu;
|
||||
|
||||
if (val)
|
||||
return -EINVAL;
|
||||
|
||||
kvm_for_each_vcpu(i, vcpu, stat_data->kvm)
|
||||
*(u64 *)((void *)vcpu + stat_data->offset) = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vcpu_stat_get_per_vm_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
__simple_attr_check_format("%llu\n", 0ull);
|
||||
return kvm_debugfs_open(inode, file, vcpu_stat_get_per_vm,
|
||||
NULL, "%llu\n");
|
||||
vcpu_stat_clear_per_vm, "%llu\n");
|
||||
}
|
||||
|
||||
static const struct file_operations vcpu_stat_get_per_vm_fops = {
|
||||
@@ -3738,7 +3768,26 @@ static int vm_stat_get(void *_offset, u64 *val)
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_SIMPLE_ATTRIBUTE(vm_stat_fops, vm_stat_get, NULL, "%llu\n");
|
||||
static int vm_stat_clear(void *_offset, u64 val)
|
||||
{
|
||||
unsigned offset = (long)_offset;
|
||||
struct kvm *kvm;
|
||||
struct kvm_stat_data stat_tmp = {.offset = offset};
|
||||
|
||||
if (val)
|
||||
return -EINVAL;
|
||||
|
||||
spin_lock(&kvm_lock);
|
||||
list_for_each_entry(kvm, &vm_list, vm_list) {
|
||||
stat_tmp.kvm = kvm;
|
||||
vm_stat_clear_per_vm((void *)&stat_tmp, 0);
|
||||
}
|
||||
spin_unlock(&kvm_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_SIMPLE_ATTRIBUTE(vm_stat_fops, vm_stat_get, vm_stat_clear, "%llu\n");
|
||||
|
||||
static int vcpu_stat_get(void *_offset, u64 *val)
|
||||
{
|
||||
@@ -3758,7 +3807,27 @@ static int vcpu_stat_get(void *_offset, u64 *val)
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_SIMPLE_ATTRIBUTE(vcpu_stat_fops, vcpu_stat_get, NULL, "%llu\n");
|
||||
static int vcpu_stat_clear(void *_offset, u64 val)
|
||||
{
|
||||
unsigned offset = (long)_offset;
|
||||
struct kvm *kvm;
|
||||
struct kvm_stat_data stat_tmp = {.offset = offset};
|
||||
|
||||
if (val)
|
||||
return -EINVAL;
|
||||
|
||||
spin_lock(&kvm_lock);
|
||||
list_for_each_entry(kvm, &vm_list, vm_list) {
|
||||
stat_tmp.kvm = kvm;
|
||||
vcpu_stat_clear_per_vm((void *)&stat_tmp, 0);
|
||||
}
|
||||
spin_unlock(&kvm_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_SIMPLE_ATTRIBUTE(vcpu_stat_fops, vcpu_stat_get, vcpu_stat_clear,
|
||||
"%llu\n");
|
||||
|
||||
static const struct file_operations *stat_fops[] = {
|
||||
[KVM_STAT_VCPU] = &vcpu_stat_fops,
|
||||
@@ -3776,7 +3845,7 @@ static int kvm_init_debug(void)
|
||||
|
||||
kvm_debugfs_num_entries = 0;
|
||||
for (p = debugfs_entries; p->name; ++p, kvm_debugfs_num_entries++) {
|
||||
if (!debugfs_create_file(p->name, 0444, kvm_debugfs_dir,
|
||||
if (!debugfs_create_file(p->name, 0644, kvm_debugfs_dir,
|
||||
(void *)(long)p->offset,
|
||||
stat_fops[p->kind]))
|
||||
goto out_dir;
|
||||
|
||||
Reference in New Issue
Block a user