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:
"First batch of KVM changes for 4.1
The most interesting bit here is irqfd/ioeventfd support for ARM and
ARM64.
Summary:
ARM/ARM64:
fixes for live migration, irqfd and ioeventfd support (enabling
vhost, too), page aging
s390:
interrupt handling rework, allowing to inject all local interrupts
via new ioctl and to get/set the full local irq state for migration
and introspection. New ioctls to access memory by virtual address,
and to get/set the guest storage keys. SIMD support.
MIPS:
FPU and MIPS SIMD Architecture (MSA) support. Includes some
patches from Ralf Baechle's MIPS tree.
x86:
bugfixes (notably for pvclock, the others are small) and cleanups.
Another small latency improvement for the TSC deadline timer"
* tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm: (146 commits)
KVM: use slowpath for cross page cached accesses
kvm: mmu: lazy collapse small sptes into large sptes
KVM: x86: Clear CR2 on VCPU reset
KVM: x86: DR0-DR3 are not clear on reset
KVM: x86: BSP in MSR_IA32_APICBASE is writable
KVM: x86: simplify kvm_apic_map
KVM: x86: avoid logical_map when it is invalid
KVM: x86: fix mixed APIC mode broadcast
KVM: x86: use MDA for interrupt matching
kvm/ppc/mpic: drop unused IRQ_testbit
KVM: nVMX: remove unnecessary double caching of MAXPHYADDR
KVM: nVMX: checks for address bits beyond MAXPHYADDR on VM-entry
KVM: x86: cache maxphyaddr CPUID leaf in struct kvm_vcpu
KVM: vmx: pass error code with internal error #2
x86: vdso: fix pvclock races with task migration
KVM: remove kvm_read_hva and kvm_read_hva_atomic
KVM: x86: optimize delivery of TSC deadline timer interrupt
KVM: x86: extract blocking logic from __vcpu_run
kvm: x86: fix x86 eflags fixed bit
KVM: s390: migrate vcpu interrupt state
...
This commit is contained in:
@@ -85,13 +85,22 @@ static irqreturn_t kvm_arch_timer_handler(int irq, void *dev_id)
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
/*
|
||||
* Work function for handling the backup timer that we schedule when a vcpu is
|
||||
* no longer running, but had a timer programmed to fire in the future.
|
||||
*/
|
||||
static void kvm_timer_inject_irq_work(struct work_struct *work)
|
||||
{
|
||||
struct kvm_vcpu *vcpu;
|
||||
|
||||
vcpu = container_of(work, struct kvm_vcpu, arch.timer_cpu.expired);
|
||||
vcpu->arch.timer_cpu.armed = false;
|
||||
kvm_timer_inject_irq(vcpu);
|
||||
|
||||
/*
|
||||
* If the vcpu is blocked we want to wake it up so that it will see
|
||||
* the timer has expired when entering the guest.
|
||||
*/
|
||||
kvm_vcpu_kick(vcpu);
|
||||
}
|
||||
|
||||
static enum hrtimer_restart kvm_timer_expire(struct hrtimer *hrt)
|
||||
@@ -102,6 +111,21 @@ static enum hrtimer_restart kvm_timer_expire(struct hrtimer *hrt)
|
||||
return HRTIMER_NORESTART;
|
||||
}
|
||||
|
||||
bool kvm_timer_should_fire(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
|
||||
cycle_t cval, now;
|
||||
|
||||
if ((timer->cntv_ctl & ARCH_TIMER_CTRL_IT_MASK) ||
|
||||
!(timer->cntv_ctl & ARCH_TIMER_CTRL_ENABLE))
|
||||
return false;
|
||||
|
||||
cval = timer->cntv_cval;
|
||||
now = kvm_phys_timer_read() - vcpu->kvm->arch.timer.cntvoff;
|
||||
|
||||
return cval <= now;
|
||||
}
|
||||
|
||||
/**
|
||||
* kvm_timer_flush_hwstate - prepare to move the virt timer to the cpu
|
||||
* @vcpu: The vcpu pointer
|
||||
@@ -119,6 +143,13 @@ void kvm_timer_flush_hwstate(struct kvm_vcpu *vcpu)
|
||||
* populate the CPU timer again.
|
||||
*/
|
||||
timer_disarm(timer);
|
||||
|
||||
/*
|
||||
* If the timer expired while we were not scheduled, now is the time
|
||||
* to inject it.
|
||||
*/
|
||||
if (kvm_timer_should_fire(vcpu))
|
||||
kvm_timer_inject_irq(vcpu);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -134,16 +165,9 @@ void kvm_timer_sync_hwstate(struct kvm_vcpu *vcpu)
|
||||
cycle_t cval, now;
|
||||
u64 ns;
|
||||
|
||||
if ((timer->cntv_ctl & ARCH_TIMER_CTRL_IT_MASK) ||
|
||||
!(timer->cntv_ctl & ARCH_TIMER_CTRL_ENABLE))
|
||||
return;
|
||||
|
||||
cval = timer->cntv_cval;
|
||||
now = kvm_phys_timer_read() - vcpu->kvm->arch.timer.cntvoff;
|
||||
|
||||
BUG_ON(timer_is_armed(timer));
|
||||
|
||||
if (cval <= now) {
|
||||
if (kvm_timer_should_fire(vcpu)) {
|
||||
/*
|
||||
* Timer has already expired while we were not
|
||||
* looking. Inject the interrupt and carry on.
|
||||
@@ -152,6 +176,9 @@ void kvm_timer_sync_hwstate(struct kvm_vcpu *vcpu)
|
||||
return;
|
||||
}
|
||||
|
||||
cval = timer->cntv_cval;
|
||||
now = kvm_phys_timer_read() - vcpu->kvm->arch.timer.cntvoff;
|
||||
|
||||
ns = cyclecounter_cyc2ns(timecounter->cc, cval - now, timecounter->mask,
|
||||
&timecounter->frac);
|
||||
timer_arm(timer, ns);
|
||||
|
||||
+40
-31
@@ -107,6 +107,22 @@ static bool handle_mmio_clear_pending_reg(struct kvm_vcpu *vcpu,
|
||||
vcpu->vcpu_id);
|
||||
}
|
||||
|
||||
static bool handle_mmio_set_active_reg(struct kvm_vcpu *vcpu,
|
||||
struct kvm_exit_mmio *mmio,
|
||||
phys_addr_t offset)
|
||||
{
|
||||
return vgic_handle_set_active_reg(vcpu->kvm, mmio, offset,
|
||||
vcpu->vcpu_id);
|
||||
}
|
||||
|
||||
static bool handle_mmio_clear_active_reg(struct kvm_vcpu *vcpu,
|
||||
struct kvm_exit_mmio *mmio,
|
||||
phys_addr_t offset)
|
||||
{
|
||||
return vgic_handle_clear_active_reg(vcpu->kvm, mmio, offset,
|
||||
vcpu->vcpu_id);
|
||||
}
|
||||
|
||||
static bool handle_mmio_priority_reg(struct kvm_vcpu *vcpu,
|
||||
struct kvm_exit_mmio *mmio,
|
||||
phys_addr_t offset)
|
||||
@@ -303,7 +319,7 @@ static bool handle_mmio_sgi_clear(struct kvm_vcpu *vcpu,
|
||||
return write_set_clear_sgi_pend_reg(vcpu, mmio, offset, false);
|
||||
}
|
||||
|
||||
static const struct kvm_mmio_range vgic_dist_ranges[] = {
|
||||
static const struct vgic_io_range vgic_dist_ranges[] = {
|
||||
{
|
||||
.base = GIC_DIST_CTRL,
|
||||
.len = 12,
|
||||
@@ -344,13 +360,13 @@ static const struct kvm_mmio_range vgic_dist_ranges[] = {
|
||||
.base = GIC_DIST_ACTIVE_SET,
|
||||
.len = VGIC_MAX_IRQS / 8,
|
||||
.bits_per_irq = 1,
|
||||
.handle_mmio = handle_mmio_raz_wi,
|
||||
.handle_mmio = handle_mmio_set_active_reg,
|
||||
},
|
||||
{
|
||||
.base = GIC_DIST_ACTIVE_CLEAR,
|
||||
.len = VGIC_MAX_IRQS / 8,
|
||||
.bits_per_irq = 1,
|
||||
.handle_mmio = handle_mmio_raz_wi,
|
||||
.handle_mmio = handle_mmio_clear_active_reg,
|
||||
},
|
||||
{
|
||||
.base = GIC_DIST_PRI,
|
||||
@@ -388,24 +404,6 @@ static const struct kvm_mmio_range vgic_dist_ranges[] = {
|
||||
{}
|
||||
};
|
||||
|
||||
static bool vgic_v2_handle_mmio(struct kvm_vcpu *vcpu, struct kvm_run *run,
|
||||
struct kvm_exit_mmio *mmio)
|
||||
{
|
||||
unsigned long base = vcpu->kvm->arch.vgic.vgic_dist_base;
|
||||
|
||||
if (!is_in_range(mmio->phys_addr, mmio->len, base,
|
||||
KVM_VGIC_V2_DIST_SIZE))
|
||||
return false;
|
||||
|
||||
/* GICv2 does not support accesses wider than 32 bits */
|
||||
if (mmio->len > 4) {
|
||||
kvm_inject_dabt(vcpu, mmio->phys_addr);
|
||||
return true;
|
||||
}
|
||||
|
||||
return vgic_handle_mmio_range(vcpu, run, mmio, vgic_dist_ranges, base);
|
||||
}
|
||||
|
||||
static void vgic_dispatch_sgi(struct kvm_vcpu *vcpu, u32 reg)
|
||||
{
|
||||
struct kvm *kvm = vcpu->kvm;
|
||||
@@ -490,6 +488,7 @@ static bool vgic_v2_queue_sgi(struct kvm_vcpu *vcpu, int irq)
|
||||
static int vgic_v2_map_resources(struct kvm *kvm,
|
||||
const struct vgic_params *params)
|
||||
{
|
||||
struct vgic_dist *dist = &kvm->arch.vgic;
|
||||
int ret = 0;
|
||||
|
||||
if (!irqchip_in_kernel(kvm))
|
||||
@@ -500,13 +499,17 @@ static int vgic_v2_map_resources(struct kvm *kvm,
|
||||
if (vgic_ready(kvm))
|
||||
goto out;
|
||||
|
||||
if (IS_VGIC_ADDR_UNDEF(kvm->arch.vgic.vgic_dist_base) ||
|
||||
IS_VGIC_ADDR_UNDEF(kvm->arch.vgic.vgic_cpu_base)) {
|
||||
if (IS_VGIC_ADDR_UNDEF(dist->vgic_dist_base) ||
|
||||
IS_VGIC_ADDR_UNDEF(dist->vgic_cpu_base)) {
|
||||
kvm_err("Need to set vgic cpu and dist addresses first\n");
|
||||
ret = -ENXIO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
vgic_register_kvm_io_dev(kvm, dist->vgic_dist_base,
|
||||
KVM_VGIC_V2_DIST_SIZE,
|
||||
vgic_dist_ranges, -1, &dist->dist_iodev);
|
||||
|
||||
/*
|
||||
* Initialize the vgic if this hasn't already been done on demand by
|
||||
* accessing the vgic state from userspace.
|
||||
@@ -514,18 +517,23 @@ static int vgic_v2_map_resources(struct kvm *kvm,
|
||||
ret = vgic_init(kvm);
|
||||
if (ret) {
|
||||
kvm_err("Unable to allocate maps\n");
|
||||
goto out;
|
||||
goto out_unregister;
|
||||
}
|
||||
|
||||
ret = kvm_phys_addr_ioremap(kvm, kvm->arch.vgic.vgic_cpu_base,
|
||||
ret = kvm_phys_addr_ioremap(kvm, dist->vgic_cpu_base,
|
||||
params->vcpu_base, KVM_VGIC_V2_CPU_SIZE,
|
||||
true);
|
||||
if (ret) {
|
||||
kvm_err("Unable to remap VGIC CPU to VCPU\n");
|
||||
goto out;
|
||||
goto out_unregister;
|
||||
}
|
||||
|
||||
kvm->arch.vgic.ready = true;
|
||||
dist->ready = true;
|
||||
goto out;
|
||||
|
||||
out_unregister:
|
||||
kvm_io_bus_unregister_dev(kvm, KVM_MMIO_BUS, &dist->dist_iodev.dev);
|
||||
|
||||
out:
|
||||
if (ret)
|
||||
kvm_vgic_destroy(kvm);
|
||||
@@ -554,7 +562,6 @@ void vgic_v2_init_emulation(struct kvm *kvm)
|
||||
{
|
||||
struct vgic_dist *dist = &kvm->arch.vgic;
|
||||
|
||||
dist->vm_ops.handle_mmio = vgic_v2_handle_mmio;
|
||||
dist->vm_ops.queue_sgi = vgic_v2_queue_sgi;
|
||||
dist->vm_ops.add_sgi_source = vgic_v2_add_sgi_source;
|
||||
dist->vm_ops.init_model = vgic_v2_init_model;
|
||||
@@ -631,7 +638,7 @@ static bool handle_cpu_mmio_ident(struct kvm_vcpu *vcpu,
|
||||
* CPU Interface Register accesses - these are not accessed by the VM, but by
|
||||
* user space for saving and restoring VGIC state.
|
||||
*/
|
||||
static const struct kvm_mmio_range vgic_cpu_ranges[] = {
|
||||
static const struct vgic_io_range vgic_cpu_ranges[] = {
|
||||
{
|
||||
.base = GIC_CPU_CTRL,
|
||||
.len = 12,
|
||||
@@ -658,12 +665,13 @@ static int vgic_attr_regs_access(struct kvm_device *dev,
|
||||
struct kvm_device_attr *attr,
|
||||
u32 *reg, bool is_write)
|
||||
{
|
||||
const struct kvm_mmio_range *r = NULL, *ranges;
|
||||
const struct vgic_io_range *r = NULL, *ranges;
|
||||
phys_addr_t offset;
|
||||
int ret, cpuid, c;
|
||||
struct kvm_vcpu *vcpu, *tmp_vcpu;
|
||||
struct vgic_dist *vgic;
|
||||
struct kvm_exit_mmio mmio;
|
||||
u32 data;
|
||||
|
||||
offset = attr->attr & KVM_DEV_ARM_VGIC_OFFSET_MASK;
|
||||
cpuid = (attr->attr & KVM_DEV_ARM_VGIC_CPUID_MASK) >>
|
||||
@@ -685,6 +693,7 @@ static int vgic_attr_regs_access(struct kvm_device *dev,
|
||||
|
||||
mmio.len = 4;
|
||||
mmio.is_write = is_write;
|
||||
mmio.data = &data;
|
||||
if (is_write)
|
||||
mmio_data_write(&mmio, ~0, *reg);
|
||||
switch (attr->group) {
|
||||
@@ -699,7 +708,7 @@ static int vgic_attr_regs_access(struct kvm_device *dev,
|
||||
default:
|
||||
BUG();
|
||||
}
|
||||
r = vgic_find_range(ranges, &mmio, offset);
|
||||
r = vgic_find_range(ranges, 4, offset);
|
||||
|
||||
if (unlikely(!r || !r->handle_mmio)) {
|
||||
ret = -ENXIO;
|
||||
|
||||
+143
-149
@@ -340,7 +340,7 @@ static bool handle_mmio_idregs(struct kvm_vcpu *vcpu,
|
||||
return false;
|
||||
}
|
||||
|
||||
static const struct kvm_mmio_range vgic_v3_dist_ranges[] = {
|
||||
static const struct vgic_io_range vgic_v3_dist_ranges[] = {
|
||||
{
|
||||
.base = GICD_CTLR,
|
||||
.len = 0x04,
|
||||
@@ -502,6 +502,43 @@ static const struct kvm_mmio_range vgic_v3_dist_ranges[] = {
|
||||
{},
|
||||
};
|
||||
|
||||
static bool handle_mmio_ctlr_redist(struct kvm_vcpu *vcpu,
|
||||
struct kvm_exit_mmio *mmio,
|
||||
phys_addr_t offset)
|
||||
{
|
||||
/* since we don't support LPIs, this register is zero for now */
|
||||
vgic_reg_access(mmio, NULL, offset,
|
||||
ACCESS_READ_RAZ | ACCESS_WRITE_IGNORED);
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool handle_mmio_typer_redist(struct kvm_vcpu *vcpu,
|
||||
struct kvm_exit_mmio *mmio,
|
||||
phys_addr_t offset)
|
||||
{
|
||||
u32 reg;
|
||||
u64 mpidr;
|
||||
struct kvm_vcpu *redist_vcpu = mmio->private;
|
||||
int target_vcpu_id = redist_vcpu->vcpu_id;
|
||||
|
||||
/* the upper 32 bits contain the affinity value */
|
||||
if ((offset & ~3) == 4) {
|
||||
mpidr = kvm_vcpu_get_mpidr_aff(redist_vcpu);
|
||||
reg = compress_mpidr(mpidr);
|
||||
|
||||
vgic_reg_access(mmio, ®, offset,
|
||||
ACCESS_READ_VALUE | ACCESS_WRITE_IGNORED);
|
||||
return false;
|
||||
}
|
||||
|
||||
reg = redist_vcpu->vcpu_id << 8;
|
||||
if (target_vcpu_id == atomic_read(&vcpu->kvm->online_vcpus) - 1)
|
||||
reg |= GICR_TYPER_LAST;
|
||||
vgic_reg_access(mmio, ®, offset,
|
||||
ACCESS_READ_VALUE | ACCESS_WRITE_IGNORED);
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool handle_mmio_set_enable_reg_redist(struct kvm_vcpu *vcpu,
|
||||
struct kvm_exit_mmio *mmio,
|
||||
phys_addr_t offset)
|
||||
@@ -570,113 +607,9 @@ static bool handle_mmio_cfg_reg_redist(struct kvm_vcpu *vcpu,
|
||||
return vgic_handle_cfg_reg(reg, mmio, offset);
|
||||
}
|
||||
|
||||
static const struct kvm_mmio_range vgic_redist_sgi_ranges[] = {
|
||||
{
|
||||
.base = GICR_IGROUPR0,
|
||||
.len = 0x04,
|
||||
.bits_per_irq = 1,
|
||||
.handle_mmio = handle_mmio_rao_wi,
|
||||
},
|
||||
{
|
||||
.base = GICR_ISENABLER0,
|
||||
.len = 0x04,
|
||||
.bits_per_irq = 1,
|
||||
.handle_mmio = handle_mmio_set_enable_reg_redist,
|
||||
},
|
||||
{
|
||||
.base = GICR_ICENABLER0,
|
||||
.len = 0x04,
|
||||
.bits_per_irq = 1,
|
||||
.handle_mmio = handle_mmio_clear_enable_reg_redist,
|
||||
},
|
||||
{
|
||||
.base = GICR_ISPENDR0,
|
||||
.len = 0x04,
|
||||
.bits_per_irq = 1,
|
||||
.handle_mmio = handle_mmio_set_pending_reg_redist,
|
||||
},
|
||||
{
|
||||
.base = GICR_ICPENDR0,
|
||||
.len = 0x04,
|
||||
.bits_per_irq = 1,
|
||||
.handle_mmio = handle_mmio_clear_pending_reg_redist,
|
||||
},
|
||||
{
|
||||
.base = GICR_ISACTIVER0,
|
||||
.len = 0x04,
|
||||
.bits_per_irq = 1,
|
||||
.handle_mmio = handle_mmio_raz_wi,
|
||||
},
|
||||
{
|
||||
.base = GICR_ICACTIVER0,
|
||||
.len = 0x04,
|
||||
.bits_per_irq = 1,
|
||||
.handle_mmio = handle_mmio_raz_wi,
|
||||
},
|
||||
{
|
||||
.base = GICR_IPRIORITYR0,
|
||||
.len = 0x20,
|
||||
.bits_per_irq = 8,
|
||||
.handle_mmio = handle_mmio_priority_reg_redist,
|
||||
},
|
||||
{
|
||||
.base = GICR_ICFGR0,
|
||||
.len = 0x08,
|
||||
.bits_per_irq = 2,
|
||||
.handle_mmio = handle_mmio_cfg_reg_redist,
|
||||
},
|
||||
{
|
||||
.base = GICR_IGRPMODR0,
|
||||
.len = 0x04,
|
||||
.bits_per_irq = 1,
|
||||
.handle_mmio = handle_mmio_raz_wi,
|
||||
},
|
||||
{
|
||||
.base = GICR_NSACR,
|
||||
.len = 0x04,
|
||||
.handle_mmio = handle_mmio_raz_wi,
|
||||
},
|
||||
{},
|
||||
};
|
||||
#define SGI_base(x) ((x) + SZ_64K)
|
||||
|
||||
static bool handle_mmio_ctlr_redist(struct kvm_vcpu *vcpu,
|
||||
struct kvm_exit_mmio *mmio,
|
||||
phys_addr_t offset)
|
||||
{
|
||||
/* since we don't support LPIs, this register is zero for now */
|
||||
vgic_reg_access(mmio, NULL, offset,
|
||||
ACCESS_READ_RAZ | ACCESS_WRITE_IGNORED);
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool handle_mmio_typer_redist(struct kvm_vcpu *vcpu,
|
||||
struct kvm_exit_mmio *mmio,
|
||||
phys_addr_t offset)
|
||||
{
|
||||
u32 reg;
|
||||
u64 mpidr;
|
||||
struct kvm_vcpu *redist_vcpu = mmio->private;
|
||||
int target_vcpu_id = redist_vcpu->vcpu_id;
|
||||
|
||||
/* the upper 32 bits contain the affinity value */
|
||||
if ((offset & ~3) == 4) {
|
||||
mpidr = kvm_vcpu_get_mpidr_aff(redist_vcpu);
|
||||
reg = compress_mpidr(mpidr);
|
||||
|
||||
vgic_reg_access(mmio, ®, offset,
|
||||
ACCESS_READ_VALUE | ACCESS_WRITE_IGNORED);
|
||||
return false;
|
||||
}
|
||||
|
||||
reg = redist_vcpu->vcpu_id << 8;
|
||||
if (target_vcpu_id == atomic_read(&vcpu->kvm->online_vcpus) - 1)
|
||||
reg |= GICR_TYPER_LAST;
|
||||
vgic_reg_access(mmio, ®, offset,
|
||||
ACCESS_READ_VALUE | ACCESS_WRITE_IGNORED);
|
||||
return false;
|
||||
}
|
||||
|
||||
static const struct kvm_mmio_range vgic_redist_ranges[] = {
|
||||
static const struct vgic_io_range vgic_redist_ranges[] = {
|
||||
{
|
||||
.base = GICR_CTLR,
|
||||
.len = 0x04,
|
||||
@@ -707,49 +640,74 @@ static const struct kvm_mmio_range vgic_redist_ranges[] = {
|
||||
.bits_per_irq = 0,
|
||||
.handle_mmio = handle_mmio_idregs,
|
||||
},
|
||||
{
|
||||
.base = SGI_base(GICR_IGROUPR0),
|
||||
.len = 0x04,
|
||||
.bits_per_irq = 1,
|
||||
.handle_mmio = handle_mmio_rao_wi,
|
||||
},
|
||||
{
|
||||
.base = SGI_base(GICR_ISENABLER0),
|
||||
.len = 0x04,
|
||||
.bits_per_irq = 1,
|
||||
.handle_mmio = handle_mmio_set_enable_reg_redist,
|
||||
},
|
||||
{
|
||||
.base = SGI_base(GICR_ICENABLER0),
|
||||
.len = 0x04,
|
||||
.bits_per_irq = 1,
|
||||
.handle_mmio = handle_mmio_clear_enable_reg_redist,
|
||||
},
|
||||
{
|
||||
.base = SGI_base(GICR_ISPENDR0),
|
||||
.len = 0x04,
|
||||
.bits_per_irq = 1,
|
||||
.handle_mmio = handle_mmio_set_pending_reg_redist,
|
||||
},
|
||||
{
|
||||
.base = SGI_base(GICR_ICPENDR0),
|
||||
.len = 0x04,
|
||||
.bits_per_irq = 1,
|
||||
.handle_mmio = handle_mmio_clear_pending_reg_redist,
|
||||
},
|
||||
{
|
||||
.base = SGI_base(GICR_ISACTIVER0),
|
||||
.len = 0x04,
|
||||
.bits_per_irq = 1,
|
||||
.handle_mmio = handle_mmio_raz_wi,
|
||||
},
|
||||
{
|
||||
.base = SGI_base(GICR_ICACTIVER0),
|
||||
.len = 0x04,
|
||||
.bits_per_irq = 1,
|
||||
.handle_mmio = handle_mmio_raz_wi,
|
||||
},
|
||||
{
|
||||
.base = SGI_base(GICR_IPRIORITYR0),
|
||||
.len = 0x20,
|
||||
.bits_per_irq = 8,
|
||||
.handle_mmio = handle_mmio_priority_reg_redist,
|
||||
},
|
||||
{
|
||||
.base = SGI_base(GICR_ICFGR0),
|
||||
.len = 0x08,
|
||||
.bits_per_irq = 2,
|
||||
.handle_mmio = handle_mmio_cfg_reg_redist,
|
||||
},
|
||||
{
|
||||
.base = SGI_base(GICR_IGRPMODR0),
|
||||
.len = 0x04,
|
||||
.bits_per_irq = 1,
|
||||
.handle_mmio = handle_mmio_raz_wi,
|
||||
},
|
||||
{
|
||||
.base = SGI_base(GICR_NSACR),
|
||||
.len = 0x04,
|
||||
.handle_mmio = handle_mmio_raz_wi,
|
||||
},
|
||||
{},
|
||||
};
|
||||
|
||||
/*
|
||||
* This function splits accesses between the distributor and the two
|
||||
* redistributor parts (private/SPI). As each redistributor is accessible
|
||||
* from any CPU, we have to determine the affected VCPU by taking the faulting
|
||||
* address into account. We then pass this VCPU to the handler function via
|
||||
* the private parameter.
|
||||
*/
|
||||
#define SGI_BASE_OFFSET SZ_64K
|
||||
static bool vgic_v3_handle_mmio(struct kvm_vcpu *vcpu, struct kvm_run *run,
|
||||
struct kvm_exit_mmio *mmio)
|
||||
{
|
||||
struct vgic_dist *dist = &vcpu->kvm->arch.vgic;
|
||||
unsigned long dbase = dist->vgic_dist_base;
|
||||
unsigned long rdbase = dist->vgic_redist_base;
|
||||
int nrcpus = atomic_read(&vcpu->kvm->online_vcpus);
|
||||
int vcpu_id;
|
||||
const struct kvm_mmio_range *mmio_range;
|
||||
|
||||
if (is_in_range(mmio->phys_addr, mmio->len, dbase, GIC_V3_DIST_SIZE)) {
|
||||
return vgic_handle_mmio_range(vcpu, run, mmio,
|
||||
vgic_v3_dist_ranges, dbase);
|
||||
}
|
||||
|
||||
if (!is_in_range(mmio->phys_addr, mmio->len, rdbase,
|
||||
GIC_V3_REDIST_SIZE * nrcpus))
|
||||
return false;
|
||||
|
||||
vcpu_id = (mmio->phys_addr - rdbase) / GIC_V3_REDIST_SIZE;
|
||||
rdbase += (vcpu_id * GIC_V3_REDIST_SIZE);
|
||||
mmio->private = kvm_get_vcpu(vcpu->kvm, vcpu_id);
|
||||
|
||||
if (mmio->phys_addr >= rdbase + SGI_BASE_OFFSET) {
|
||||
rdbase += SGI_BASE_OFFSET;
|
||||
mmio_range = vgic_redist_sgi_ranges;
|
||||
} else {
|
||||
mmio_range = vgic_redist_ranges;
|
||||
}
|
||||
return vgic_handle_mmio_range(vcpu, run, mmio, mmio_range, rdbase);
|
||||
}
|
||||
|
||||
static bool vgic_v3_queue_sgi(struct kvm_vcpu *vcpu, int irq)
|
||||
{
|
||||
if (vgic_queue_irq(vcpu, 0, irq)) {
|
||||
@@ -766,6 +724,9 @@ static int vgic_v3_map_resources(struct kvm *kvm,
|
||||
{
|
||||
int ret = 0;
|
||||
struct vgic_dist *dist = &kvm->arch.vgic;
|
||||
gpa_t rdbase = dist->vgic_redist_base;
|
||||
struct vgic_io_device *iodevs = NULL;
|
||||
int i;
|
||||
|
||||
if (!irqchip_in_kernel(kvm))
|
||||
return 0;
|
||||
@@ -791,7 +752,41 @@ static int vgic_v3_map_resources(struct kvm *kvm,
|
||||
goto out;
|
||||
}
|
||||
|
||||
kvm->arch.vgic.ready = true;
|
||||
ret = vgic_register_kvm_io_dev(kvm, dist->vgic_dist_base,
|
||||
GIC_V3_DIST_SIZE, vgic_v3_dist_ranges,
|
||||
-1, &dist->dist_iodev);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
iodevs = kcalloc(dist->nr_cpus, sizeof(iodevs[0]), GFP_KERNEL);
|
||||
if (!iodevs) {
|
||||
ret = -ENOMEM;
|
||||
goto out_unregister;
|
||||
}
|
||||
|
||||
for (i = 0; i < dist->nr_cpus; i++) {
|
||||
ret = vgic_register_kvm_io_dev(kvm, rdbase,
|
||||
SZ_128K, vgic_redist_ranges,
|
||||
i, &iodevs[i]);
|
||||
if (ret)
|
||||
goto out_unregister;
|
||||
rdbase += GIC_V3_REDIST_SIZE;
|
||||
}
|
||||
|
||||
dist->redist_iodevs = iodevs;
|
||||
dist->ready = true;
|
||||
goto out;
|
||||
|
||||
out_unregister:
|
||||
kvm_io_bus_unregister_dev(kvm, KVM_MMIO_BUS, &dist->dist_iodev.dev);
|
||||
if (iodevs) {
|
||||
for (i = 0; i < dist->nr_cpus; i++) {
|
||||
if (iodevs[i].dev.ops)
|
||||
kvm_io_bus_unregister_dev(kvm, KVM_MMIO_BUS,
|
||||
&iodevs[i].dev);
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
if (ret)
|
||||
kvm_vgic_destroy(kvm);
|
||||
@@ -832,7 +827,6 @@ void vgic_v3_init_emulation(struct kvm *kvm)
|
||||
{
|
||||
struct vgic_dist *dist = &kvm->arch.vgic;
|
||||
|
||||
dist->vm_ops.handle_mmio = vgic_v3_handle_mmio;
|
||||
dist->vm_ops.queue_sgi = vgic_v3_queue_sgi;
|
||||
dist->vm_ops.add_sgi_source = vgic_v3_add_sgi_source;
|
||||
dist->vm_ops.init_model = vgic_v3_init_model;
|
||||
|
||||
+361
-122
File diff suppressed because it is too large
Load Diff
+27
-10
@@ -20,6 +20,8 @@
|
||||
#ifndef __KVM_VGIC_H__
|
||||
#define __KVM_VGIC_H__
|
||||
|
||||
#include <kvm/iodev.h>
|
||||
|
||||
#define VGIC_ADDR_UNDEF (-1)
|
||||
#define IS_VGIC_ADDR_UNDEF(_x) ((_x) == VGIC_ADDR_UNDEF)
|
||||
|
||||
@@ -57,6 +59,14 @@ void vgic_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
|
||||
bool vgic_queue_irq(struct kvm_vcpu *vcpu, u8 sgi_source_id, int irq);
|
||||
void vgic_unqueue_irqs(struct kvm_vcpu *vcpu);
|
||||
|
||||
struct kvm_exit_mmio {
|
||||
phys_addr_t phys_addr;
|
||||
void *data;
|
||||
u32 len;
|
||||
bool is_write;
|
||||
void *private;
|
||||
};
|
||||
|
||||
void vgic_reg_access(struct kvm_exit_mmio *mmio, u32 *reg,
|
||||
phys_addr_t offset, int mode);
|
||||
bool handle_mmio_raz_wi(struct kvm_vcpu *vcpu, struct kvm_exit_mmio *mmio,
|
||||
@@ -74,7 +84,7 @@ void mmio_data_write(struct kvm_exit_mmio *mmio, u32 mask, u32 value)
|
||||
*((u32 *)mmio->data) = cpu_to_le32(value) & mask;
|
||||
}
|
||||
|
||||
struct kvm_mmio_range {
|
||||
struct vgic_io_range {
|
||||
phys_addr_t base;
|
||||
unsigned long len;
|
||||
int bits_per_irq;
|
||||
@@ -82,6 +92,11 @@ struct kvm_mmio_range {
|
||||
phys_addr_t offset);
|
||||
};
|
||||
|
||||
int vgic_register_kvm_io_dev(struct kvm *kvm, gpa_t base, int len,
|
||||
const struct vgic_io_range *ranges,
|
||||
int redist_id,
|
||||
struct vgic_io_device *iodev);
|
||||
|
||||
static inline bool is_in_range(phys_addr_t addr, unsigned long len,
|
||||
phys_addr_t baseaddr, unsigned long size)
|
||||
{
|
||||
@@ -89,14 +104,8 @@ static inline bool is_in_range(phys_addr_t addr, unsigned long len,
|
||||
}
|
||||
|
||||
const
|
||||
struct kvm_mmio_range *vgic_find_range(const struct kvm_mmio_range *ranges,
|
||||
struct kvm_exit_mmio *mmio,
|
||||
phys_addr_t offset);
|
||||
|
||||
bool vgic_handle_mmio_range(struct kvm_vcpu *vcpu, struct kvm_run *run,
|
||||
struct kvm_exit_mmio *mmio,
|
||||
const struct kvm_mmio_range *ranges,
|
||||
unsigned long mmio_base);
|
||||
struct vgic_io_range *vgic_find_range(const struct vgic_io_range *ranges,
|
||||
int len, gpa_t offset);
|
||||
|
||||
bool vgic_handle_enable_reg(struct kvm *kvm, struct kvm_exit_mmio *mmio,
|
||||
phys_addr_t offset, int vcpu_id, int access);
|
||||
@@ -107,12 +116,20 @@ bool vgic_handle_set_pending_reg(struct kvm *kvm, struct kvm_exit_mmio *mmio,
|
||||
bool vgic_handle_clear_pending_reg(struct kvm *kvm, struct kvm_exit_mmio *mmio,
|
||||
phys_addr_t offset, int vcpu_id);
|
||||
|
||||
bool vgic_handle_set_active_reg(struct kvm *kvm,
|
||||
struct kvm_exit_mmio *mmio,
|
||||
phys_addr_t offset, int vcpu_id);
|
||||
|
||||
bool vgic_handle_clear_active_reg(struct kvm *kvm,
|
||||
struct kvm_exit_mmio *mmio,
|
||||
phys_addr_t offset, int vcpu_id);
|
||||
|
||||
bool vgic_handle_cfg_reg(u32 *reg, struct kvm_exit_mmio *mmio,
|
||||
phys_addr_t offset);
|
||||
|
||||
void vgic_kick_vcpus(struct kvm *kvm);
|
||||
|
||||
int vgic_has_attr_regs(const struct kvm_mmio_range *ranges, phys_addr_t offset);
|
||||
int vgic_has_attr_regs(const struct vgic_io_range *ranges, phys_addr_t offset);
|
||||
int vgic_set_common_attr(struct kvm_device *dev, struct kvm_device_attr *attr);
|
||||
int vgic_get_common_attr(struct kvm_device *dev, struct kvm_device_attr *attr);
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "iodev.h"
|
||||
#include <kvm/iodev.h>
|
||||
|
||||
#include <linux/kvm_host.h>
|
||||
#include <linux/slab.h>
|
||||
@@ -60,8 +60,9 @@ static int coalesced_mmio_has_room(struct kvm_coalesced_mmio_dev *dev)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int coalesced_mmio_write(struct kvm_io_device *this,
|
||||
gpa_t addr, int len, const void *val)
|
||||
static int coalesced_mmio_write(struct kvm_vcpu *vcpu,
|
||||
struct kvm_io_device *this, gpa_t addr,
|
||||
int len, const void *val)
|
||||
{
|
||||
struct kvm_coalesced_mmio_dev *dev = to_mmio(this);
|
||||
struct kvm_coalesced_mmio_ring *ring = dev->kvm->coalesced_mmio_ring;
|
||||
|
||||
+6
-3
@@ -36,7 +36,7 @@
|
||||
#include <linux/seqlock.h>
|
||||
#include <trace/events/kvm.h>
|
||||
|
||||
#include "iodev.h"
|
||||
#include <kvm/iodev.h>
|
||||
|
||||
#ifdef CONFIG_HAVE_KVM_IRQFD
|
||||
/*
|
||||
@@ -311,6 +311,9 @@ kvm_irqfd_assign(struct kvm *kvm, struct kvm_irqfd *args)
|
||||
unsigned int events;
|
||||
int idx;
|
||||
|
||||
if (!kvm_arch_intc_initialized(kvm))
|
||||
return -EAGAIN;
|
||||
|
||||
irqfd = kzalloc(sizeof(*irqfd), GFP_KERNEL);
|
||||
if (!irqfd)
|
||||
return -ENOMEM;
|
||||
@@ -712,8 +715,8 @@ ioeventfd_in_range(struct _ioeventfd *p, gpa_t addr, int len, const void *val)
|
||||
|
||||
/* MMIO/PIO writes trigger an event if the addr/val match */
|
||||
static int
|
||||
ioeventfd_write(struct kvm_io_device *this, gpa_t addr, int len,
|
||||
const void *val)
|
||||
ioeventfd_write(struct kvm_vcpu *vcpu, struct kvm_io_device *this, gpa_t addr,
|
||||
int len, const void *val)
|
||||
{
|
||||
struct _ioeventfd *p = to_ioeventfd(this);
|
||||
|
||||
|
||||
@@ -1,70 +0,0 @@
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef __KVM_IODEV_H__
|
||||
#define __KVM_IODEV_H__
|
||||
|
||||
#include <linux/kvm_types.h>
|
||||
#include <asm/errno.h>
|
||||
|
||||
struct kvm_io_device;
|
||||
|
||||
/**
|
||||
* kvm_io_device_ops are called under kvm slots_lock.
|
||||
* read and write handlers return 0 if the transaction has been handled,
|
||||
* or non-zero to have it passed to the next device.
|
||||
**/
|
||||
struct kvm_io_device_ops {
|
||||
int (*read)(struct kvm_io_device *this,
|
||||
gpa_t addr,
|
||||
int len,
|
||||
void *val);
|
||||
int (*write)(struct kvm_io_device *this,
|
||||
gpa_t addr,
|
||||
int len,
|
||||
const void *val);
|
||||
void (*destructor)(struct kvm_io_device *this);
|
||||
};
|
||||
|
||||
|
||||
struct kvm_io_device {
|
||||
const struct kvm_io_device_ops *ops;
|
||||
};
|
||||
|
||||
static inline void kvm_iodevice_init(struct kvm_io_device *dev,
|
||||
const struct kvm_io_device_ops *ops)
|
||||
{
|
||||
dev->ops = ops;
|
||||
}
|
||||
|
||||
static inline int kvm_iodevice_read(struct kvm_io_device *dev,
|
||||
gpa_t addr, int l, void *v)
|
||||
{
|
||||
return dev->ops->read ? dev->ops->read(dev, addr, l, v) : -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static inline int kvm_iodevice_write(struct kvm_io_device *dev,
|
||||
gpa_t addr, int l, const void *v)
|
||||
{
|
||||
return dev->ops->write ? dev->ops->write(dev, addr, l, v) : -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static inline void kvm_iodevice_destructor(struct kvm_io_device *dev)
|
||||
{
|
||||
if (dev->ops->destructor)
|
||||
dev->ops->destructor(dev);
|
||||
}
|
||||
|
||||
#endif /* __KVM_IODEV_H__ */
|
||||
+1
-1
@@ -105,7 +105,7 @@ int kvm_set_irq(struct kvm *kvm, int irq_source_id, u32 irq, int level,
|
||||
i = kvm_irq_map_gsi(kvm, irq_set, irq);
|
||||
srcu_read_unlock(&kvm->irq_srcu, idx);
|
||||
|
||||
while(i--) {
|
||||
while (i--) {
|
||||
int r;
|
||||
r = irq_set[i].set(&irq_set[i], kvm, irq_source_id, level,
|
||||
line_status);
|
||||
|
||||
+68
-80
@@ -16,7 +16,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "iodev.h"
|
||||
#include <kvm/iodev.h>
|
||||
|
||||
#include <linux/kvm_host.h>
|
||||
#include <linux/kvm.h>
|
||||
@@ -66,13 +66,13 @@
|
||||
MODULE_AUTHOR("Qumranet");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
unsigned int halt_poll_ns = 0;
|
||||
static unsigned int halt_poll_ns;
|
||||
module_param(halt_poll_ns, uint, S_IRUGO | S_IWUSR);
|
||||
|
||||
/*
|
||||
* Ordering of locks:
|
||||
*
|
||||
* kvm->lock --> kvm->slots_lock --> kvm->irq_lock
|
||||
* kvm->lock --> kvm->slots_lock --> kvm->irq_lock
|
||||
*/
|
||||
|
||||
DEFINE_SPINLOCK(kvm_lock);
|
||||
@@ -80,7 +80,7 @@ static DEFINE_RAW_SPINLOCK(kvm_count_lock);
|
||||
LIST_HEAD(vm_list);
|
||||
|
||||
static cpumask_var_t cpus_hardware_enabled;
|
||||
static int kvm_usage_count = 0;
|
||||
static int kvm_usage_count;
|
||||
static atomic_t hardware_enable_failed;
|
||||
|
||||
struct kmem_cache *kvm_vcpu_cache;
|
||||
@@ -539,20 +539,12 @@ void *kvm_kvzalloc(unsigned long size)
|
||||
return kzalloc(size, GFP_KERNEL);
|
||||
}
|
||||
|
||||
void kvm_kvfree(const void *addr)
|
||||
{
|
||||
if (is_vmalloc_addr(addr))
|
||||
vfree(addr);
|
||||
else
|
||||
kfree(addr);
|
||||
}
|
||||
|
||||
static void kvm_destroy_dirty_bitmap(struct kvm_memory_slot *memslot)
|
||||
{
|
||||
if (!memslot->dirty_bitmap)
|
||||
return;
|
||||
|
||||
kvm_kvfree(memslot->dirty_bitmap);
|
||||
kvfree(memslot->dirty_bitmap);
|
||||
memslot->dirty_bitmap = NULL;
|
||||
}
|
||||
|
||||
@@ -888,8 +880,8 @@ int __kvm_set_memory_region(struct kvm *kvm,
|
||||
* or moved, memslot will be created.
|
||||
*
|
||||
* validation of sp->gfn happens in:
|
||||
* - gfn_to_hva (kvm_read_guest, gfn_to_pfn)
|
||||
* - kvm_is_visible_gfn (mmu_check_roots)
|
||||
* - gfn_to_hva (kvm_read_guest, gfn_to_pfn)
|
||||
* - kvm_is_visible_gfn (mmu_check_roots)
|
||||
*/
|
||||
kvm_arch_flush_shadow_memslot(kvm, slot);
|
||||
|
||||
@@ -1061,9 +1053,11 @@ int kvm_get_dirty_log_protect(struct kvm *kvm,
|
||||
mask = xchg(&dirty_bitmap[i], 0);
|
||||
dirty_bitmap_buffer[i] = mask;
|
||||
|
||||
offset = i * BITS_PER_LONG;
|
||||
kvm_arch_mmu_enable_log_dirty_pt_masked(kvm, memslot, offset,
|
||||
mask);
|
||||
if (mask) {
|
||||
offset = i * BITS_PER_LONG;
|
||||
kvm_arch_mmu_enable_log_dirty_pt_masked(kvm, memslot,
|
||||
offset, mask);
|
||||
}
|
||||
}
|
||||
|
||||
spin_unlock(&kvm->mmu_lock);
|
||||
@@ -1193,16 +1187,6 @@ unsigned long gfn_to_hva_prot(struct kvm *kvm, gfn_t gfn, bool *writable)
|
||||
return gfn_to_hva_memslot_prot(slot, gfn, writable);
|
||||
}
|
||||
|
||||
static int kvm_read_hva(void *data, void __user *hva, int len)
|
||||
{
|
||||
return __copy_from_user(data, hva, len);
|
||||
}
|
||||
|
||||
static int kvm_read_hva_atomic(void *data, void __user *hva, int len)
|
||||
{
|
||||
return __copy_from_user_inatomic(data, hva, len);
|
||||
}
|
||||
|
||||
static int get_user_page_nowait(struct task_struct *tsk, struct mm_struct *mm,
|
||||
unsigned long start, int write, struct page **page)
|
||||
{
|
||||
@@ -1481,7 +1465,6 @@ struct page *gfn_to_page(struct kvm *kvm, gfn_t gfn)
|
||||
|
||||
return kvm_pfn_to_page(pfn);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL_GPL(gfn_to_page);
|
||||
|
||||
void kvm_release_page_clean(struct page *page)
|
||||
@@ -1517,6 +1500,7 @@ void kvm_set_pfn_dirty(pfn_t pfn)
|
||||
{
|
||||
if (!kvm_is_reserved_pfn(pfn)) {
|
||||
struct page *page = pfn_to_page(pfn);
|
||||
|
||||
if (!PageReserved(page))
|
||||
SetPageDirty(page);
|
||||
}
|
||||
@@ -1554,7 +1538,7 @@ int kvm_read_guest_page(struct kvm *kvm, gfn_t gfn, void *data, int offset,
|
||||
addr = gfn_to_hva_prot(kvm, gfn, NULL);
|
||||
if (kvm_is_error_hva(addr))
|
||||
return -EFAULT;
|
||||
r = kvm_read_hva(data, (void __user *)addr + offset, len);
|
||||
r = __copy_from_user(data, (void __user *)addr + offset, len);
|
||||
if (r)
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
@@ -1593,7 +1577,7 @@ int kvm_read_guest_atomic(struct kvm *kvm, gpa_t gpa, void *data,
|
||||
if (kvm_is_error_hva(addr))
|
||||
return -EFAULT;
|
||||
pagefault_disable();
|
||||
r = kvm_read_hva_atomic(data, (void __user *)addr + offset, len);
|
||||
r = __copy_from_user_inatomic(data, (void __user *)addr + offset, len);
|
||||
pagefault_enable();
|
||||
if (r)
|
||||
return -EFAULT;
|
||||
@@ -1653,8 +1637,8 @@ int kvm_gfn_to_hva_cache_init(struct kvm *kvm, struct gfn_to_hva_cache *ghc,
|
||||
ghc->generation = slots->generation;
|
||||
ghc->len = len;
|
||||
ghc->memslot = gfn_to_memslot(kvm, start_gfn);
|
||||
ghc->hva = gfn_to_hva_many(ghc->memslot, start_gfn, &nr_pages_avail);
|
||||
if (!kvm_is_error_hva(ghc->hva) && nr_pages_avail >= nr_pages_needed) {
|
||||
ghc->hva = gfn_to_hva_many(ghc->memslot, start_gfn, NULL);
|
||||
if (!kvm_is_error_hva(ghc->hva) && nr_pages_needed <= 1) {
|
||||
ghc->hva += offset;
|
||||
} else {
|
||||
/*
|
||||
@@ -1742,7 +1726,7 @@ int kvm_clear_guest(struct kvm *kvm, gpa_t gpa, unsigned long len)
|
||||
int offset = offset_in_page(gpa);
|
||||
int ret;
|
||||
|
||||
while ((seg = next_segment(len, offset)) != 0) {
|
||||
while ((seg = next_segment(len, offset)) != 0) {
|
||||
ret = kvm_clear_guest_page(kvm, gfn, offset, seg);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
@@ -1800,6 +1784,7 @@ void kvm_vcpu_block(struct kvm_vcpu *vcpu)
|
||||
start = cur = ktime_get();
|
||||
if (halt_poll_ns) {
|
||||
ktime_t stop = ktime_add_ns(ktime_get(), halt_poll_ns);
|
||||
|
||||
do {
|
||||
/*
|
||||
* This sets KVM_REQ_UNHALT if an interrupt
|
||||
@@ -2118,7 +2103,7 @@ static long kvm_vcpu_ioctl(struct file *filp,
|
||||
* Special cases: vcpu ioctls that are asynchronous to vcpu execution,
|
||||
* so vcpu_load() would break it.
|
||||
*/
|
||||
if (ioctl == KVM_S390_INTERRUPT || ioctl == KVM_INTERRUPT)
|
||||
if (ioctl == KVM_S390_INTERRUPT || ioctl == KVM_S390_IRQ || ioctl == KVM_INTERRUPT)
|
||||
return kvm_arch_vcpu_ioctl(filp, ioctl, arg);
|
||||
#endif
|
||||
|
||||
@@ -2135,6 +2120,7 @@ static long kvm_vcpu_ioctl(struct file *filp,
|
||||
/* The thread running this VCPU changed. */
|
||||
struct pid *oldpid = vcpu->pid;
|
||||
struct pid *newpid = get_task_pid(current, PIDTYPE_PID);
|
||||
|
||||
rcu_assign_pointer(vcpu->pid, newpid);
|
||||
if (oldpid)
|
||||
synchronize_rcu();
|
||||
@@ -2205,7 +2191,7 @@ out_free1:
|
||||
if (r)
|
||||
goto out;
|
||||
r = -EFAULT;
|
||||
if (copy_to_user(argp, &mp_state, sizeof mp_state))
|
||||
if (copy_to_user(argp, &mp_state, sizeof(mp_state)))
|
||||
goto out;
|
||||
r = 0;
|
||||
break;
|
||||
@@ -2214,7 +2200,7 @@ out_free1:
|
||||
struct kvm_mp_state mp_state;
|
||||
|
||||
r = -EFAULT;
|
||||
if (copy_from_user(&mp_state, argp, sizeof mp_state))
|
||||
if (copy_from_user(&mp_state, argp, sizeof(mp_state)))
|
||||
goto out;
|
||||
r = kvm_arch_vcpu_ioctl_set_mpstate(vcpu, &mp_state);
|
||||
break;
|
||||
@@ -2223,13 +2209,13 @@ out_free1:
|
||||
struct kvm_translation tr;
|
||||
|
||||
r = -EFAULT;
|
||||
if (copy_from_user(&tr, argp, sizeof tr))
|
||||
if (copy_from_user(&tr, argp, sizeof(tr)))
|
||||
goto out;
|
||||
r = kvm_arch_vcpu_ioctl_translate(vcpu, &tr);
|
||||
if (r)
|
||||
goto out;
|
||||
r = -EFAULT;
|
||||
if (copy_to_user(argp, &tr, sizeof tr))
|
||||
if (copy_to_user(argp, &tr, sizeof(tr)))
|
||||
goto out;
|
||||
r = 0;
|
||||
break;
|
||||
@@ -2238,7 +2224,7 @@ out_free1:
|
||||
struct kvm_guest_debug dbg;
|
||||
|
||||
r = -EFAULT;
|
||||
if (copy_from_user(&dbg, argp, sizeof dbg))
|
||||
if (copy_from_user(&dbg, argp, sizeof(dbg)))
|
||||
goto out;
|
||||
r = kvm_arch_vcpu_ioctl_set_guest_debug(vcpu, &dbg);
|
||||
break;
|
||||
@@ -2252,14 +2238,14 @@ out_free1:
|
||||
if (argp) {
|
||||
r = -EFAULT;
|
||||
if (copy_from_user(&kvm_sigmask, argp,
|
||||
sizeof kvm_sigmask))
|
||||
sizeof(kvm_sigmask)))
|
||||
goto out;
|
||||
r = -EINVAL;
|
||||
if (kvm_sigmask.len != sizeof sigset)
|
||||
if (kvm_sigmask.len != sizeof(sigset))
|
||||
goto out;
|
||||
r = -EFAULT;
|
||||
if (copy_from_user(&sigset, sigmask_arg->sigset,
|
||||
sizeof sigset))
|
||||
sizeof(sigset)))
|
||||
goto out;
|
||||
p = &sigset;
|
||||
}
|
||||
@@ -2321,14 +2307,14 @@ static long kvm_vcpu_compat_ioctl(struct file *filp,
|
||||
if (argp) {
|
||||
r = -EFAULT;
|
||||
if (copy_from_user(&kvm_sigmask, argp,
|
||||
sizeof kvm_sigmask))
|
||||
sizeof(kvm_sigmask)))
|
||||
goto out;
|
||||
r = -EINVAL;
|
||||
if (kvm_sigmask.len != sizeof csigset)
|
||||
if (kvm_sigmask.len != sizeof(csigset))
|
||||
goto out;
|
||||
r = -EFAULT;
|
||||
if (copy_from_user(&csigset, sigmask_arg->sigset,
|
||||
sizeof csigset))
|
||||
sizeof(csigset)))
|
||||
goto out;
|
||||
sigset_from_compat(&sigset, &csigset);
|
||||
r = kvm_vcpu_ioctl_set_sigmask(vcpu, &sigset);
|
||||
@@ -2525,7 +2511,7 @@ static long kvm_vm_ioctl(struct file *filp,
|
||||
|
||||
r = -EFAULT;
|
||||
if (copy_from_user(&kvm_userspace_mem, argp,
|
||||
sizeof kvm_userspace_mem))
|
||||
sizeof(kvm_userspace_mem)))
|
||||
goto out;
|
||||
|
||||
r = kvm_vm_ioctl_set_memory_region(kvm, &kvm_userspace_mem);
|
||||
@@ -2535,7 +2521,7 @@ static long kvm_vm_ioctl(struct file *filp,
|
||||
struct kvm_dirty_log log;
|
||||
|
||||
r = -EFAULT;
|
||||
if (copy_from_user(&log, argp, sizeof log))
|
||||
if (copy_from_user(&log, argp, sizeof(log)))
|
||||
goto out;
|
||||
r = kvm_vm_ioctl_get_dirty_log(kvm, &log);
|
||||
break;
|
||||
@@ -2543,16 +2529,18 @@ static long kvm_vm_ioctl(struct file *filp,
|
||||
#ifdef KVM_COALESCED_MMIO_PAGE_OFFSET
|
||||
case KVM_REGISTER_COALESCED_MMIO: {
|
||||
struct kvm_coalesced_mmio_zone zone;
|
||||
|
||||
r = -EFAULT;
|
||||
if (copy_from_user(&zone, argp, sizeof zone))
|
||||
if (copy_from_user(&zone, argp, sizeof(zone)))
|
||||
goto out;
|
||||
r = kvm_vm_ioctl_register_coalesced_mmio(kvm, &zone);
|
||||
break;
|
||||
}
|
||||
case KVM_UNREGISTER_COALESCED_MMIO: {
|
||||
struct kvm_coalesced_mmio_zone zone;
|
||||
|
||||
r = -EFAULT;
|
||||
if (copy_from_user(&zone, argp, sizeof zone))
|
||||
if (copy_from_user(&zone, argp, sizeof(zone)))
|
||||
goto out;
|
||||
r = kvm_vm_ioctl_unregister_coalesced_mmio(kvm, &zone);
|
||||
break;
|
||||
@@ -2562,7 +2550,7 @@ static long kvm_vm_ioctl(struct file *filp,
|
||||
struct kvm_irqfd data;
|
||||
|
||||
r = -EFAULT;
|
||||
if (copy_from_user(&data, argp, sizeof data))
|
||||
if (copy_from_user(&data, argp, sizeof(data)))
|
||||
goto out;
|
||||
r = kvm_irqfd(kvm, &data);
|
||||
break;
|
||||
@@ -2571,7 +2559,7 @@ static long kvm_vm_ioctl(struct file *filp,
|
||||
struct kvm_ioeventfd data;
|
||||
|
||||
r = -EFAULT;
|
||||
if (copy_from_user(&data, argp, sizeof data))
|
||||
if (copy_from_user(&data, argp, sizeof(data)))
|
||||
goto out;
|
||||
r = kvm_ioeventfd(kvm, &data);
|
||||
break;
|
||||
@@ -2592,7 +2580,7 @@ static long kvm_vm_ioctl(struct file *filp,
|
||||
struct kvm_msi msi;
|
||||
|
||||
r = -EFAULT;
|
||||
if (copy_from_user(&msi, argp, sizeof msi))
|
||||
if (copy_from_user(&msi, argp, sizeof(msi)))
|
||||
goto out;
|
||||
r = kvm_send_userspace_msi(kvm, &msi);
|
||||
break;
|
||||
@@ -2604,7 +2592,7 @@ static long kvm_vm_ioctl(struct file *filp,
|
||||
struct kvm_irq_level irq_event;
|
||||
|
||||
r = -EFAULT;
|
||||
if (copy_from_user(&irq_event, argp, sizeof irq_event))
|
||||
if (copy_from_user(&irq_event, argp, sizeof(irq_event)))
|
||||
goto out;
|
||||
|
||||
r = kvm_vm_ioctl_irq_line(kvm, &irq_event,
|
||||
@@ -2614,7 +2602,7 @@ static long kvm_vm_ioctl(struct file *filp,
|
||||
|
||||
r = -EFAULT;
|
||||
if (ioctl == KVM_IRQ_LINE_STATUS) {
|
||||
if (copy_to_user(argp, &irq_event, sizeof irq_event))
|
||||
if (copy_to_user(argp, &irq_event, sizeof(irq_event)))
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -2647,7 +2635,7 @@ static long kvm_vm_ioctl(struct file *filp,
|
||||
goto out_free_irq_routing;
|
||||
r = kvm_set_irq_routing(kvm, entries, routing.nr,
|
||||
routing.flags);
|
||||
out_free_irq_routing:
|
||||
out_free_irq_routing:
|
||||
vfree(entries);
|
||||
break;
|
||||
}
|
||||
@@ -2822,8 +2810,7 @@ static void hardware_enable_nolock(void *junk)
|
||||
if (r) {
|
||||
cpumask_clear_cpu(cpu, cpus_hardware_enabled);
|
||||
atomic_inc(&hardware_enable_failed);
|
||||
printk(KERN_INFO "kvm: enabling virtualization on "
|
||||
"CPU%d failed\n", cpu);
|
||||
pr_info("kvm: enabling virtualization on CPU%d failed\n", cpu);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2899,12 +2886,12 @@ static int kvm_cpu_hotplug(struct notifier_block *notifier, unsigned long val,
|
||||
val &= ~CPU_TASKS_FROZEN;
|
||||
switch (val) {
|
||||
case CPU_DYING:
|
||||
printk(KERN_INFO "kvm: disabling virtualization on CPU%d\n",
|
||||
pr_info("kvm: disabling virtualization on CPU%d\n",
|
||||
cpu);
|
||||
hardware_disable();
|
||||
break;
|
||||
case CPU_STARTING:
|
||||
printk(KERN_INFO "kvm: enabling virtualization on CPU%d\n",
|
||||
pr_info("kvm: enabling virtualization on CPU%d\n",
|
||||
cpu);
|
||||
hardware_enable();
|
||||
break;
|
||||
@@ -2921,7 +2908,7 @@ static int kvm_reboot(struct notifier_block *notifier, unsigned long val,
|
||||
*
|
||||
* And Intel TXT required VMX off for all cpu when system shutdown.
|
||||
*/
|
||||
printk(KERN_INFO "kvm: exiting hardware virtualization\n");
|
||||
pr_info("kvm: exiting hardware virtualization\n");
|
||||
kvm_rebooting = true;
|
||||
on_each_cpu(hardware_disable_nolock, NULL, 1);
|
||||
return NOTIFY_OK;
|
||||
@@ -2945,7 +2932,7 @@ static void kvm_io_bus_destroy(struct kvm_io_bus *bus)
|
||||
}
|
||||
|
||||
static inline int kvm_io_bus_cmp(const struct kvm_io_range *r1,
|
||||
const struct kvm_io_range *r2)
|
||||
const struct kvm_io_range *r2)
|
||||
{
|
||||
if (r1->addr < r2->addr)
|
||||
return -1;
|
||||
@@ -2998,7 +2985,7 @@ static int kvm_io_bus_get_first_dev(struct kvm_io_bus *bus,
|
||||
return off;
|
||||
}
|
||||
|
||||
static int __kvm_io_bus_write(struct kvm_io_bus *bus,
|
||||
static int __kvm_io_bus_write(struct kvm_vcpu *vcpu, struct kvm_io_bus *bus,
|
||||
struct kvm_io_range *range, const void *val)
|
||||
{
|
||||
int idx;
|
||||
@@ -3009,7 +2996,7 @@ static int __kvm_io_bus_write(struct kvm_io_bus *bus,
|
||||
|
||||
while (idx < bus->dev_count &&
|
||||
kvm_io_bus_cmp(range, &bus->range[idx]) == 0) {
|
||||
if (!kvm_iodevice_write(bus->range[idx].dev, range->addr,
|
||||
if (!kvm_iodevice_write(vcpu, bus->range[idx].dev, range->addr,
|
||||
range->len, val))
|
||||
return idx;
|
||||
idx++;
|
||||
@@ -3019,7 +3006,7 @@ static int __kvm_io_bus_write(struct kvm_io_bus *bus,
|
||||
}
|
||||
|
||||
/* kvm_io_bus_write - called under kvm->slots_lock */
|
||||
int kvm_io_bus_write(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
|
||||
int kvm_io_bus_write(struct kvm_vcpu *vcpu, enum kvm_bus bus_idx, gpa_t addr,
|
||||
int len, const void *val)
|
||||
{
|
||||
struct kvm_io_bus *bus;
|
||||
@@ -3031,14 +3018,14 @@ int kvm_io_bus_write(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
|
||||
.len = len,
|
||||
};
|
||||
|
||||
bus = srcu_dereference(kvm->buses[bus_idx], &kvm->srcu);
|
||||
r = __kvm_io_bus_write(bus, &range, val);
|
||||
bus = srcu_dereference(vcpu->kvm->buses[bus_idx], &vcpu->kvm->srcu);
|
||||
r = __kvm_io_bus_write(vcpu, bus, &range, val);
|
||||
return r < 0 ? r : 0;
|
||||
}
|
||||
|
||||
/* kvm_io_bus_write_cookie - called under kvm->slots_lock */
|
||||
int kvm_io_bus_write_cookie(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
|
||||
int len, const void *val, long cookie)
|
||||
int kvm_io_bus_write_cookie(struct kvm_vcpu *vcpu, enum kvm_bus bus_idx,
|
||||
gpa_t addr, int len, const void *val, long cookie)
|
||||
{
|
||||
struct kvm_io_bus *bus;
|
||||
struct kvm_io_range range;
|
||||
@@ -3048,12 +3035,12 @@ int kvm_io_bus_write_cookie(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
|
||||
.len = len,
|
||||
};
|
||||
|
||||
bus = srcu_dereference(kvm->buses[bus_idx], &kvm->srcu);
|
||||
bus = srcu_dereference(vcpu->kvm->buses[bus_idx], &vcpu->kvm->srcu);
|
||||
|
||||
/* First try the device referenced by cookie. */
|
||||
if ((cookie >= 0) && (cookie < bus->dev_count) &&
|
||||
(kvm_io_bus_cmp(&range, &bus->range[cookie]) == 0))
|
||||
if (!kvm_iodevice_write(bus->range[cookie].dev, addr, len,
|
||||
if (!kvm_iodevice_write(vcpu, bus->range[cookie].dev, addr, len,
|
||||
val))
|
||||
return cookie;
|
||||
|
||||
@@ -3061,11 +3048,11 @@ int kvm_io_bus_write_cookie(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
|
||||
* cookie contained garbage; fall back to search and return the
|
||||
* correct cookie value.
|
||||
*/
|
||||
return __kvm_io_bus_write(bus, &range, val);
|
||||
return __kvm_io_bus_write(vcpu, bus, &range, val);
|
||||
}
|
||||
|
||||
static int __kvm_io_bus_read(struct kvm_io_bus *bus, struct kvm_io_range *range,
|
||||
void *val)
|
||||
static int __kvm_io_bus_read(struct kvm_vcpu *vcpu, struct kvm_io_bus *bus,
|
||||
struct kvm_io_range *range, void *val)
|
||||
{
|
||||
int idx;
|
||||
|
||||
@@ -3075,7 +3062,7 @@ static int __kvm_io_bus_read(struct kvm_io_bus *bus, struct kvm_io_range *range,
|
||||
|
||||
while (idx < bus->dev_count &&
|
||||
kvm_io_bus_cmp(range, &bus->range[idx]) == 0) {
|
||||
if (!kvm_iodevice_read(bus->range[idx].dev, range->addr,
|
||||
if (!kvm_iodevice_read(vcpu, bus->range[idx].dev, range->addr,
|
||||
range->len, val))
|
||||
return idx;
|
||||
idx++;
|
||||
@@ -3086,7 +3073,7 @@ static int __kvm_io_bus_read(struct kvm_io_bus *bus, struct kvm_io_range *range,
|
||||
EXPORT_SYMBOL_GPL(kvm_io_bus_write);
|
||||
|
||||
/* kvm_io_bus_read - called under kvm->slots_lock */
|
||||
int kvm_io_bus_read(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
|
||||
int kvm_io_bus_read(struct kvm_vcpu *vcpu, enum kvm_bus bus_idx, gpa_t addr,
|
||||
int len, void *val)
|
||||
{
|
||||
struct kvm_io_bus *bus;
|
||||
@@ -3098,8 +3085,8 @@ int kvm_io_bus_read(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
|
||||
.len = len,
|
||||
};
|
||||
|
||||
bus = srcu_dereference(kvm->buses[bus_idx], &kvm->srcu);
|
||||
r = __kvm_io_bus_read(bus, &range, val);
|
||||
bus = srcu_dereference(vcpu->kvm->buses[bus_idx], &vcpu->kvm->srcu);
|
||||
r = __kvm_io_bus_read(vcpu, bus, &range, val);
|
||||
return r < 0 ? r : 0;
|
||||
}
|
||||
|
||||
@@ -3269,6 +3256,7 @@ struct kvm_vcpu *preempt_notifier_to_vcpu(struct preempt_notifier *pn)
|
||||
static void kvm_sched_in(struct preempt_notifier *pn, int cpu)
|
||||
{
|
||||
struct kvm_vcpu *vcpu = preempt_notifier_to_vcpu(pn);
|
||||
|
||||
if (vcpu->preempted)
|
||||
vcpu->preempted = false;
|
||||
|
||||
@@ -3350,7 +3338,7 @@ int kvm_init(void *opaque, unsigned vcpu_size, unsigned vcpu_align,
|
||||
|
||||
r = misc_register(&kvm_dev);
|
||||
if (r) {
|
||||
printk(KERN_ERR "kvm: misc device register failed\n");
|
||||
pr_err("kvm: misc device register failed\n");
|
||||
goto out_unreg;
|
||||
}
|
||||
|
||||
@@ -3361,7 +3349,7 @@ int kvm_init(void *opaque, unsigned vcpu_size, unsigned vcpu_align,
|
||||
|
||||
r = kvm_init_debug();
|
||||
if (r) {
|
||||
printk(KERN_ERR "kvm: create debugfs files failed\n");
|
||||
pr_err("kvm: create debugfs files failed\n");
|
||||
goto out_undebugfs;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user