Commit e9a999fe authored by Jes Sorensen's avatar Jes Sorensen Committed by Avi Kivity

KVM: ia64: stack get/restore patch

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: default avatarJes Sorensen <jes@sgi.com>
Signed-off-by: default avatarAvi Kivity <avi@redhat.com>
parent ae675ef0
...@@ -214,6 +214,13 @@ struct kvm_sregs { ...@@ -214,6 +214,13 @@ struct kvm_sregs {
struct kvm_fpu { 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 { struct kvm_debug_exit_arch {
}; };
......
...@@ -112,7 +112,11 @@ ...@@ -112,7 +112,11 @@
#define VCPU_STRUCT_SHIFT 16 #define VCPU_STRUCT_SHIFT 16
#define VCPU_STRUCT_SIZE (__IA64_UL_CONST(1) << VCPU_STRUCT_SHIFT) #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_SHIFT 19
#define KVM_VM_STRUCT_SIZE (__IA64_UL_CONST(1) << KVM_VM_STRUCT_SHIFT) #define KVM_VM_STRUCT_SIZE (__IA64_UL_CONST(1) << KVM_VM_STRUCT_SHIFT)
......
...@@ -1421,6 +1421,23 @@ int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs) ...@@ -1421,6 +1421,23 @@ int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
return 0; 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) void kvm_arch_vcpu_uninit(struct kvm_vcpu *vcpu)
{ {
...@@ -1430,9 +1447,78 @@ void kvm_arch_vcpu_uninit(struct kvm_vcpu *vcpu) ...@@ -1430,9 +1447,78 @@ void kvm_arch_vcpu_uninit(struct kvm_vcpu *vcpu)
long kvm_arch_vcpu_ioctl(struct file *filp, 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, int kvm_arch_set_memory_region(struct kvm *kvm,
...@@ -1472,7 +1558,7 @@ void kvm_arch_flush_shadow(struct kvm *kvm) ...@@ -1472,7 +1558,7 @@ void kvm_arch_flush_shadow(struct kvm *kvm)
} }
long kvm_arch_dev_ioctl(struct file *filp, long kvm_arch_dev_ioctl(struct file *filp,
unsigned int ioctl, unsigned long arg) unsigned int ioctl, unsigned long arg)
{ {
return -EINVAL; return -EINVAL;
} }
......
...@@ -489,6 +489,9 @@ struct kvm_debug_guest { ...@@ -489,6 +489,9 @@ struct kvm_debug_guest {
#define __KVM_DEPRECATED_DEBUG_GUEST _IOW(KVMIO, 0x87, 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_INJ_VIRQ (KVM_TRC_HANDLER + 0x02)
#define KVM_TRC_REDELIVER_EVT (KVM_TRC_HANDLER + 0x03) #define KVM_TRC_REDELIVER_EVT (KVM_TRC_HANDLER + 0x03)
#define KVM_TRC_PEND_INTR (KVM_TRC_HANDLER + 0x04) #define KVM_TRC_PEND_INTR (KVM_TRC_HANDLER + 0x04)
......
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