Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 80649
b: refs/heads/master
c: 6fc138d
h: refs/heads/master
i:
  80647: 3a3c3b9
v: v3
  • Loading branch information
Izik Eidus authored and Avi Kivity committed Jan 30, 2008
1 parent 9d770db commit 4d8e7d6
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 12 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: d77c26fce93d07802db97498959587eb9347b31d
refs/heads/master: 6fc138d2278078990f597cb1f62fde9e5b458f96
1 change: 1 addition & 0 deletions trunk/drivers/kvm/kvm.h
Original file line number Diff line number Diff line change
Expand Up @@ -408,6 +408,7 @@ struct kvm_memory_slot {
struct page **phys_mem;
unsigned long *rmap;
unsigned long *dirty_bitmap;
int user_alloc; /* user allocated memory */
};

struct kvm {
Expand Down
81 changes: 70 additions & 11 deletions trunk/drivers/kvm/kvm_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
#include <linux/anon_inodes.h>
#include <linux/profile.h>
#include <linux/kvm_para.h>
#include <linux/pagemap.h>

#include <asm/processor.h>
#include <asm/msr.h>
Expand Down Expand Up @@ -300,19 +301,40 @@ static struct kvm *kvm_create_vm(void)
return kvm;
}

static void kvm_free_userspace_physmem(struct kvm_memory_slot *free)
{
int i;

for (i = 0; i < free->npages; ++i) {
if (free->phys_mem[i]) {
if (!PageReserved(free->phys_mem[i]))
SetPageDirty(free->phys_mem[i]);
page_cache_release(free->phys_mem[i]);
}
}
}

static void kvm_free_kernel_physmem(struct kvm_memory_slot *free)
{
int i;

for (i = 0; i < free->npages; ++i)
if (free->phys_mem[i])
__free_page(free->phys_mem[i]);
}

/*
* Free any memory in @free but not in @dont.
*/
static void kvm_free_physmem_slot(struct kvm_memory_slot *free,
struct kvm_memory_slot *dont)
{
int i;

if (!dont || free->phys_mem != dont->phys_mem)
if (free->phys_mem) {
for (i = 0; i < free->npages; ++i)
if (free->phys_mem[i])
__free_page(free->phys_mem[i]);
if (free->user_alloc)
kvm_free_userspace_physmem(free);
else
kvm_free_kernel_physmem(free);
vfree(free->phys_mem);
}
if (!dont || free->rmap != dont->rmap)
Expand Down Expand Up @@ -652,7 +674,9 @@ EXPORT_SYMBOL_GPL(fx_init);
* Discontiguous memory is allowed, mostly for framebuffers.
*/
static int kvm_vm_ioctl_set_memory_region(struct kvm *kvm,
struct kvm_memory_region *mem)
struct
kvm_userspace_memory_region *mem,
int user_alloc)
{
int r;
gfn_t base_gfn;
Expand Down Expand Up @@ -728,11 +752,27 @@ static int kvm_vm_ioctl_set_memory_region(struct kvm *kvm,

memset(new.phys_mem, 0, npages * sizeof(struct page *));
memset(new.rmap, 0, npages * sizeof(*new.rmap));
for (i = 0; i < npages; ++i) {
new.phys_mem[i] = alloc_page(GFP_HIGHUSER
| __GFP_ZERO);
if (!new.phys_mem[i])
if (user_alloc) {
unsigned long pages_num;

new.user_alloc = 1;
down_read(&current->mm->mmap_sem);

pages_num = get_user_pages(current, current->mm,
mem->userspace_addr,
npages, 1, 1, new.phys_mem,
NULL);

up_read(&current->mm->mmap_sem);
if (pages_num != npages)
goto out_unlock;
} else {
for (i = 0; i < npages; ++i) {
new.phys_mem[i] = alloc_page(GFP_HIGHUSER
| __GFP_ZERO);
if (!new.phys_mem[i])
goto out_unlock;
}
}
}

Expand Down Expand Up @@ -3108,11 +3148,29 @@ static long kvm_vm_ioctl(struct file *filp,
break;
case KVM_SET_MEMORY_REGION: {
struct kvm_memory_region kvm_mem;
struct kvm_userspace_memory_region kvm_userspace_mem;

r = -EFAULT;
if (copy_from_user(&kvm_mem, argp, sizeof kvm_mem))
goto out;
r = kvm_vm_ioctl_set_memory_region(kvm, &kvm_mem);
kvm_userspace_mem.slot = kvm_mem.slot;
kvm_userspace_mem.flags = kvm_mem.flags;
kvm_userspace_mem.guest_phys_addr = kvm_mem.guest_phys_addr;
kvm_userspace_mem.memory_size = kvm_mem.memory_size;
r = kvm_vm_ioctl_set_memory_region(kvm, &kvm_userspace_mem, 0);
if (r)
goto out;
break;
}
case KVM_SET_USER_MEMORY_REGION: {
struct kvm_userspace_memory_region kvm_userspace_mem;

r = -EFAULT;
if (copy_from_user(&kvm_userspace_mem, argp,
sizeof kvm_userspace_mem))
goto out;

r = kvm_vm_ioctl_set_memory_region(kvm, &kvm_userspace_mem, 1);
if (r)
goto out;
break;
Expand Down Expand Up @@ -3332,6 +3390,7 @@ static long kvm_dev_ioctl(struct file *filp,
case KVM_CAP_IRQCHIP:
case KVM_CAP_HLT:
case KVM_CAP_MMU_SHADOW_CACHE_CONTROL:
case KVM_CAP_USER_MEMORY:
r = 1;
break;
default:
Expand Down
12 changes: 12 additions & 0 deletions trunk/include/linux/kvm.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,15 @@ struct kvm_memory_region {
__u64 memory_size; /* bytes */
};

/* for KVM_SET_USER_MEMORY_REGION */
struct kvm_userspace_memory_region {
__u32 slot;
__u32 flags;
__u64 guest_phys_addr;
__u64 memory_size; /* bytes */
__u64 userspace_addr; /* start of the userspace allocated memory */
};

/* for kvm_memory_region::flags */
#define KVM_MEM_LOG_DIRTY_PAGES 1UL

Expand Down Expand Up @@ -348,13 +357,16 @@ struct kvm_signal_mask {
#define KVM_CAP_IRQCHIP 0
#define KVM_CAP_HLT 1
#define KVM_CAP_MMU_SHADOW_CACHE_CONTROL 2
#define KVM_CAP_USER_MEMORY 3

/*
* ioctls for VM fds
*/
#define KVM_SET_MEMORY_REGION _IOW(KVMIO, 0x40, struct kvm_memory_region)
#define KVM_SET_NR_MMU_PAGES _IO(KVMIO, 0x44)
#define KVM_GET_NR_MMU_PAGES _IO(KVMIO, 0x45)
#define KVM_SET_USER_MEMORY_REGION _IOW(KVMIO, 0x46,\
struct kvm_userspace_memory_region)
/*
* KVM_CREATE_VCPU receives as a parameter the vcpu slot, and returns
* a vcpu fd.
Expand Down

0 comments on commit 4d8e7d6

Please sign in to comment.