Skip to content

Commit

Permalink
KVM: ia64: stack get/restore patch
Browse files Browse the repository at this point in the history
Implement KVM_IA64_VCPU_[GS]ET_STACK ioctl calls. This is required
for live migrations.

Patch is based on previous implementation that was part of old
GET/SET_REGS ioctl calls.

Signed-off-by: Jes Sorensen <jes@sgi.com>
Signed-off-by: Avi Kivity <avi@redhat.com>
  • Loading branch information
Jes Sorensen authored and Avi Kivity committed Mar 24, 2009
1 parent ae675ef commit e9a999f
Show file tree
Hide file tree
Showing 4 changed files with 104 additions and 4 deletions.
7 changes: 7 additions & 0 deletions arch/ia64/include/asm/kvm.h
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,13 @@ struct kvm_sregs {
struct kvm_fpu {
};

#define KVM_IA64_VCPU_STACK_SHIFT 16
#define KVM_IA64_VCPU_STACK_SIZE (1UL << KVM_IA64_VCPU_STACK_SHIFT)

struct kvm_ia64_vcpu_stack {
unsigned char stack[KVM_IA64_VCPU_STACK_SIZE];
};

struct kvm_debug_exit_arch {
};

Expand Down
6 changes: 5 additions & 1 deletion arch/ia64/include/asm/kvm_host.h
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,11 @@
#define VCPU_STRUCT_SHIFT 16
#define VCPU_STRUCT_SIZE (__IA64_UL_CONST(1) << VCPU_STRUCT_SHIFT)

#define KVM_STK_OFFSET VCPU_STRUCT_SIZE
/*
* This must match KVM_IA64_VCPU_STACK_{SHIFT,SIZE} arch/ia64/include/asm/kvm.h
*/
#define KVM_STK_SHIFT 16
#define KVM_STK_OFFSET (__IA64_UL_CONST(1)<< KVM_STK_SHIFT)

#define KVM_VM_STRUCT_SHIFT 19
#define KVM_VM_STRUCT_SIZE (__IA64_UL_CONST(1) << KVM_VM_STRUCT_SHIFT)
Expand Down
92 changes: 89 additions & 3 deletions arch/ia64/kvm/kvm-ia64.c
Original file line number Diff line number Diff line change
Expand Up @@ -1421,6 +1421,23 @@ int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
return 0;
}

int kvm_arch_vcpu_ioctl_get_stack(struct kvm_vcpu *vcpu,
struct kvm_ia64_vcpu_stack *stack)
{
memcpy(stack, vcpu, sizeof(struct kvm_ia64_vcpu_stack));
return 0;
}

int kvm_arch_vcpu_ioctl_set_stack(struct kvm_vcpu *vcpu,
struct kvm_ia64_vcpu_stack *stack)
{
memcpy(vcpu + 1, &stack->stack[0] + sizeof(struct kvm_vcpu),
sizeof(struct kvm_ia64_vcpu_stack) - sizeof(struct kvm_vcpu));

vcpu->arch.exit_data = ((struct kvm_vcpu *)stack)->arch.exit_data;
return 0;
}

void kvm_arch_vcpu_uninit(struct kvm_vcpu *vcpu)
{

Expand All @@ -1430,9 +1447,78 @@ void kvm_arch_vcpu_uninit(struct kvm_vcpu *vcpu)


long kvm_arch_vcpu_ioctl(struct file *filp,
unsigned int ioctl, unsigned long arg)
unsigned int ioctl, unsigned long arg)
{
return -EINVAL;
struct kvm_vcpu *vcpu = filp->private_data;
void __user *argp = (void __user *)arg;
struct kvm_ia64_vcpu_stack *stack = NULL;
long r;

switch (ioctl) {
case KVM_IA64_VCPU_GET_STACK: {
struct kvm_ia64_vcpu_stack __user *user_stack;
void __user *first_p = argp;

r = -EFAULT;
if (copy_from_user(&user_stack, first_p, sizeof(void *)))
goto out;

if (!access_ok(VERIFY_WRITE, user_stack,
sizeof(struct kvm_ia64_vcpu_stack))) {
printk(KERN_INFO "KVM_IA64_VCPU_GET_STACK: "
"Illegal user destination address for stack\n");
goto out;
}
stack = kzalloc(sizeof(struct kvm_ia64_vcpu_stack), GFP_KERNEL);
if (!stack) {
r = -ENOMEM;
goto out;
}

r = kvm_arch_vcpu_ioctl_get_stack(vcpu, stack);
if (r)
goto out;

if (copy_to_user(user_stack, stack,
sizeof(struct kvm_ia64_vcpu_stack)))
goto out;

break;
}
case KVM_IA64_VCPU_SET_STACK: {
struct kvm_ia64_vcpu_stack __user *user_stack;
void __user *first_p = argp;

r = -EFAULT;
if (copy_from_user(&user_stack, first_p, sizeof(void *)))
goto out;

if (!access_ok(VERIFY_READ, user_stack,
sizeof(struct kvm_ia64_vcpu_stack))) {
printk(KERN_INFO "KVM_IA64_VCPU_SET_STACK: "
"Illegal user address for stack\n");
goto out;
}
stack = kmalloc(sizeof(struct kvm_ia64_vcpu_stack), GFP_KERNEL);
if (!stack) {
r = -ENOMEM;
goto out;
}
if (copy_from_user(stack, user_stack,
sizeof(struct kvm_ia64_vcpu_stack)))
goto out;

r = kvm_arch_vcpu_ioctl_set_stack(vcpu, stack);
break;
}

default:
r = -EINVAL;
}

out:
kfree(stack);
return r;
}

int kvm_arch_set_memory_region(struct kvm *kvm,
Expand Down Expand Up @@ -1472,7 +1558,7 @@ void kvm_arch_flush_shadow(struct kvm *kvm)
}

long kvm_arch_dev_ioctl(struct file *filp,
unsigned int ioctl, unsigned long arg)
unsigned int ioctl, unsigned long arg)
{
return -EINVAL;
}
Expand Down
3 changes: 3 additions & 0 deletions include/linux/kvm.h
Original file line number Diff line number Diff line change
Expand Up @@ -489,6 +489,9 @@ struct kvm_debug_guest {

#define __KVM_DEPRECATED_DEBUG_GUEST _IOW(KVMIO, 0x87, struct kvm_debug_guest)

#define KVM_IA64_VCPU_GET_STACK _IOR(KVMIO, 0x9a, void *)
#define KVM_IA64_VCPU_SET_STACK _IOW(KVMIO, 0x9b, void *)

#define KVM_TRC_INJ_VIRQ (KVM_TRC_HANDLER + 0x02)
#define KVM_TRC_REDELIVER_EVT (KVM_TRC_HANDLER + 0x03)
#define KVM_TRC_PEND_INTR (KVM_TRC_HANDLER + 0x04)
Expand Down

0 comments on commit e9a999f

Please sign in to comment.