Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 93844
b: refs/heads/master
c: b0c632d
h: refs/heads/master
v: v3
  • Loading branch information
Heiko Carstens authored and Avi Kivity committed Apr 27, 2008
1 parent ff81fe6 commit 006f696
Show file tree
Hide file tree
Showing 13 changed files with 1,146 additions and 3 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: 8a88ac6183975c73c65b45f365f6f3b875c1348b
refs/heads/master: b0c632db637d68ad39d9f97f452ce176253f5f4e
2 changes: 1 addition & 1 deletion trunk/arch/s390/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ LDFLAGS_vmlinux := -e start
head-y := arch/s390/kernel/head.o arch/s390/kernel/init_task.o

core-y += arch/s390/mm/ arch/s390/kernel/ arch/s390/crypto/ \
arch/s390/appldata/ arch/s390/hypfs/
arch/s390/appldata/ arch/s390/hypfs/ arch/s390/kvm/
libs-y += arch/s390/lib/
drivers-y += drivers/s390/
drivers-$(CONFIG_MATHEMU) += arch/s390/math-emu/
Expand Down
1 change: 1 addition & 0 deletions trunk/arch/s390/kernel/vtime.c
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ void account_system_vtime(struct task_struct *tsk)
S390_lowcore.steal_clock -= cputime << 12;
account_system_time(tsk, 0, cputime);
}
EXPORT_SYMBOL_GPL(account_system_vtime);

static inline void set_vtimer(__u64 expires)
{
Expand Down
14 changes: 14 additions & 0 deletions trunk/arch/s390/kvm/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Makefile for kernel virtual machines on s390
#
# Copyright IBM Corp. 2008
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License (version 2 only)
# as published by the Free Software Foundation.

common-objs = $(addprefix ../../../virt/kvm/, kvm_main.o)

EXTRA_CFLAGS += -Ivirt/kvm -Iarch/s390/kvm

kvm-objs := $(common-objs) kvm-s390.o sie64a.o
obj-$(CONFIG_KVM) += kvm.o
274 changes: 274 additions & 0 deletions trunk/arch/s390/kvm/gaccess.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,274 @@
/*
* gaccess.h - access guest memory
*
* Copyright IBM Corp. 2008
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License (version 2 only)
* as published by the Free Software Foundation.
*
* Author(s): Carsten Otte <cotte@de.ibm.com>
*/

#ifndef __KVM_S390_GACCESS_H
#define __KVM_S390_GACCESS_H

#include <linux/compiler.h>
#include <linux/kvm_host.h>
#include <asm/uaccess.h>

static inline void __user *__guestaddr_to_user(struct kvm_vcpu *vcpu,
u64 guestaddr)
{
u64 prefix = vcpu->arch.sie_block->prefix;
u64 origin = vcpu->kvm->arch.guest_origin;
u64 memsize = vcpu->kvm->arch.guest_memsize;

if (guestaddr < 2 * PAGE_SIZE)
guestaddr += prefix;
else if ((guestaddr >= prefix) && (guestaddr < prefix + 2 * PAGE_SIZE))
guestaddr -= prefix;

if (guestaddr > memsize)
return (void __user __force *) ERR_PTR(-EFAULT);

guestaddr += origin;

return (void __user *) guestaddr;
}

static inline int get_guest_u64(struct kvm_vcpu *vcpu, u64 guestaddr,
u64 *result)
{
void __user *uptr = __guestaddr_to_user(vcpu, guestaddr);

BUG_ON(guestaddr & 7);

if (IS_ERR((void __force *) uptr))
return PTR_ERR((void __force *) uptr);

return get_user(*result, (u64 __user *) uptr);
}

static inline int get_guest_u32(struct kvm_vcpu *vcpu, u64 guestaddr,
u32 *result)
{
void __user *uptr = __guestaddr_to_user(vcpu, guestaddr);

BUG_ON(guestaddr & 3);

if (IS_ERR((void __force *) uptr))
return PTR_ERR((void __force *) uptr);

return get_user(*result, (u32 __user *) uptr);
}

static inline int get_guest_u16(struct kvm_vcpu *vcpu, u64 guestaddr,
u16 *result)
{
void __user *uptr = __guestaddr_to_user(vcpu, guestaddr);

BUG_ON(guestaddr & 1);

if (IS_ERR(uptr))
return PTR_ERR(uptr);

return get_user(*result, (u16 __user *) uptr);
}

static inline int get_guest_u8(struct kvm_vcpu *vcpu, u64 guestaddr,
u8 *result)
{
void __user *uptr = __guestaddr_to_user(vcpu, guestaddr);

if (IS_ERR((void __force *) uptr))
return PTR_ERR((void __force *) uptr);

return get_user(*result, (u8 __user *) uptr);
}

static inline int put_guest_u64(struct kvm_vcpu *vcpu, u64 guestaddr,
u64 value)
{
void __user *uptr = __guestaddr_to_user(vcpu, guestaddr);

BUG_ON(guestaddr & 7);

if (IS_ERR((void __force *) uptr))
return PTR_ERR((void __force *) uptr);

return put_user(value, (u64 __user *) uptr);
}

static inline int put_guest_u32(struct kvm_vcpu *vcpu, u64 guestaddr,
u32 value)
{
void __user *uptr = __guestaddr_to_user(vcpu, guestaddr);

BUG_ON(guestaddr & 3);

if (IS_ERR((void __force *) uptr))
return PTR_ERR((void __force *) uptr);

return put_user(value, (u32 __user *) uptr);
}

static inline int put_guest_u16(struct kvm_vcpu *vcpu, u64 guestaddr,
u16 value)
{
void __user *uptr = __guestaddr_to_user(vcpu, guestaddr);

BUG_ON(guestaddr & 1);

if (IS_ERR((void __force *) uptr))
return PTR_ERR((void __force *) uptr);

return put_user(value, (u16 __user *) uptr);
}

static inline int put_guest_u8(struct kvm_vcpu *vcpu, u64 guestaddr,
u8 value)
{
void __user *uptr = __guestaddr_to_user(vcpu, guestaddr);

if (IS_ERR((void __force *) uptr))
return PTR_ERR((void __force *) uptr);

return put_user(value, (u8 __user *) uptr);
}


static inline int __copy_to_guest_slow(struct kvm_vcpu *vcpu, u64 guestdest,
const void *from, unsigned long n)
{
int rc;
unsigned long i;
const u8 *data = from;

for (i = 0; i < n; i++) {
rc = put_guest_u8(vcpu, guestdest++, *(data++));
if (rc < 0)
return rc;
}
return 0;
}

static inline int copy_to_guest(struct kvm_vcpu *vcpu, u64 guestdest,
const void *from, unsigned long n)
{
u64 prefix = vcpu->arch.sie_block->prefix;
u64 origin = vcpu->kvm->arch.guest_origin;
u64 memsize = vcpu->kvm->arch.guest_memsize;

if ((guestdest < 2 * PAGE_SIZE) && (guestdest + n > 2 * PAGE_SIZE))
goto slowpath;

if ((guestdest < prefix) && (guestdest + n > prefix))
goto slowpath;

if ((guestdest < prefix + 2 * PAGE_SIZE)
&& (guestdest + n > prefix + 2 * PAGE_SIZE))
goto slowpath;

if (guestdest < 2 * PAGE_SIZE)
guestdest += prefix;
else if ((guestdest >= prefix) && (guestdest < prefix + 2 * PAGE_SIZE))
guestdest -= prefix;

if (guestdest + n > memsize)
return -EFAULT;

if (guestdest + n < guestdest)
return -EFAULT;

guestdest += origin;

return copy_to_user((void __user *) guestdest, from, n);
slowpath:
return __copy_to_guest_slow(vcpu, guestdest, from, n);
}

static inline int __copy_from_guest_slow(struct kvm_vcpu *vcpu, void *to,
u64 guestsrc, unsigned long n)
{
int rc;
unsigned long i;
u8 *data = to;

for (i = 0; i < n; i++) {
rc = get_guest_u8(vcpu, guestsrc++, data++);
if (rc < 0)
return rc;
}
return 0;
}

static inline int copy_from_guest(struct kvm_vcpu *vcpu, void *to,
u64 guestsrc, unsigned long n)
{
u64 prefix = vcpu->arch.sie_block->prefix;
u64 origin = vcpu->kvm->arch.guest_origin;
u64 memsize = vcpu->kvm->arch.guest_memsize;

if ((guestsrc < 2 * PAGE_SIZE) && (guestsrc + n > 2 * PAGE_SIZE))
goto slowpath;

if ((guestsrc < prefix) && (guestsrc + n > prefix))
goto slowpath;

if ((guestsrc < prefix + 2 * PAGE_SIZE)
&& (guestsrc + n > prefix + 2 * PAGE_SIZE))
goto slowpath;

if (guestsrc < 2 * PAGE_SIZE)
guestsrc += prefix;
else if ((guestsrc >= prefix) && (guestsrc < prefix + 2 * PAGE_SIZE))
guestsrc -= prefix;

if (guestsrc + n > memsize)
return -EFAULT;

if (guestsrc + n < guestsrc)
return -EFAULT;

guestsrc += origin;

return copy_from_user(to, (void __user *) guestsrc, n);
slowpath:
return __copy_from_guest_slow(vcpu, to, guestsrc, n);
}

static inline int copy_to_guest_absolute(struct kvm_vcpu *vcpu, u64 guestdest,
const void *from, unsigned long n)
{
u64 origin = vcpu->kvm->arch.guest_origin;
u64 memsize = vcpu->kvm->arch.guest_memsize;

if (guestdest + n > memsize)
return -EFAULT;

if (guestdest + n < guestdest)
return -EFAULT;

guestdest += origin;

return copy_to_user((void __user *) guestdest, from, n);
}

static inline int copy_from_guest_absolute(struct kvm_vcpu *vcpu, void *to,
u64 guestsrc, unsigned long n)
{
u64 origin = vcpu->kvm->arch.guest_origin;
u64 memsize = vcpu->kvm->arch.guest_memsize;

if (guestsrc + n > memsize)
return -EFAULT;

if (guestsrc + n < guestsrc)
return -EFAULT;

guestsrc += origin;

return copy_from_user(to, (void __user *) guestsrc, n);
}
#endif
Loading

0 comments on commit 006f696

Please sign in to comment.