summaryrefslogtreecommitdiff
path: root/libkvm
diff options
context:
space:
mode:
authorCarsten Otte <cotte@de.ibm.com>2008-07-17 17:28:25 +0200
committerAvi Kivity <avi@qumranet.com>2008-07-19 10:56:07 +0300
commitde3c8887aba71bc517404f6ac518656274bc534b (patch)
tree66100908294d018a7f2fc5ff3746cab29799e772 /libkvm
parent4773d38679d4e487dfd3db815eeb7e22278688f7 (diff)
kvm: libkvm: s390 port
Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com> Signed-off-by: Avi Kivity <avi@qumranet.com>
Diffstat (limited to 'libkvm')
-rw-r--r--libkvm/config-s390.mak3
-rw-r--r--libkvm/config-s390x.mak3
-rw-r--r--libkvm/kvm-common.h7
-rw-r--r--libkvm/kvm-s390.h31
-rw-r--r--libkvm/libkvm-s390.c131
-rw-r--r--libkvm/libkvm.c23
-rw-r--r--libkvm/libkvm.h17
7 files changed, 214 insertions, 1 deletions
diff --git a/libkvm/config-s390.mak b/libkvm/config-s390.mak
new file mode 100644
index 00000000..8177e4ad
--- /dev/null
+++ b/libkvm/config-s390.mak
@@ -0,0 +1,3 @@
+# s390 31bit mode
+LIBDIR := /lib
+libkvm-$(ARCH)-objs := libkvm-s390.o
diff --git a/libkvm/config-s390x.mak b/libkvm/config-s390x.mak
new file mode 100644
index 00000000..f08ed3d8
--- /dev/null
+++ b/libkvm/config-s390x.mak
@@ -0,0 +1,3 @@
+# s390 64 bit mode (arch=s390x)
+LIBDIR := /lib64
+libkvm-$(ARCH)-objs := libkvm-s390.o
diff --git a/libkvm/kvm-common.h b/libkvm/kvm-common.h
index 9780fb85..7092085a 100644
--- a/libkvm/kvm-common.h
+++ b/libkvm/kvm-common.h
@@ -18,8 +18,15 @@
/* FIXME: share this number with kvm */
/* FIXME: or dynamically alloc/realloc regions */
+#ifndef __s390__
#define KVM_MAX_NUM_MEM_REGIONS 8u
#define MAX_VCPUS 16
+#else
+#define KVM_MAX_NUM_MEM_REGIONS 1u
+#define MAX_VCPUS 64
+#define LIBKVM_S390_ORIGIN (0UL)
+#endif
+
/* kvm abi verison variable */
extern int kvm_abi;
diff --git a/libkvm/kvm-s390.h b/libkvm/kvm-s390.h
new file mode 100644
index 00000000..9edd9a33
--- /dev/null
+++ b/libkvm/kvm-s390.h
@@ -0,0 +1,31 @@
+/*
+ * This header is for functions & variables that will ONLY be
+ * used inside libkvm for s390.
+ * THESE ARE NOT EXPOSED TO THE USER AND ARE ONLY FOR USE
+ * WITHIN LIBKVM.
+ *
+ * Copyright (C) 2006 Qumranet, Inc.
+ *
+ * Authors:
+ * Avi Kivity <avi@qumranet.com>
+ * Yaniv Kamay <yaniv@qumranet.com>
+ *
+ * Copyright 2008 IBM Corporation.
+ * Authors:
+ * Carsten Otte <cotte@de.ibm.com>
+ *
+ * This work is licensed under the GNU LGPL license, version 2.
+ */
+
+#ifndef KVM_S390_H
+#define KVM_S390_H
+
+#include <asm/ptrace.h>
+#include "kvm-common.h"
+
+#define PAGE_SIZE 4096ul
+#define PAGE_MASK (~(PAGE_SIZE - 1))
+
+#define smp_wmb() asm volatile("" ::: "memory")
+
+#endif
diff --git a/libkvm/libkvm-s390.c b/libkvm/libkvm-s390.c
new file mode 100644
index 00000000..b3e4e92f
--- /dev/null
+++ b/libkvm/libkvm-s390.c
@@ -0,0 +1,131 @@
+/*
+ * This file contains the s390 specific implementation for the
+ * architecture dependent functions defined in kvm-common.h and
+ * libkvm.h
+ *
+ * Copyright (C) 2006 Qumranet
+ * Copyright IBM Corp. 2008
+ *
+ * Authors:
+ * Carsten Otte <cotte@de.ibm.com>
+ * Christian Borntraeger <borntraeger@de.ibm.com>
+ *
+ * This work is licensed under the GNU LGPL license, version 2.
+ */
+
+#include <sys/ioctl.h>
+#include <asm/ptrace.h>
+
+#include "libkvm.h"
+#include "kvm-common.h"
+#include <errno.h>
+#include <stdio.h>
+#include <inttypes.h>
+
+int kvm_alloc_kernel_memory(kvm_context_t kvm, unsigned long memory,
+ void **vm_mem)
+{
+ fprintf(stderr, "%s: Operation not supported\n", __FUNCTION__);
+ return -1;
+}
+
+void *kvm_create_kernel_phys_mem(kvm_context_t kvm, unsigned long phys_start,
+ unsigned long len, int log, int writable)
+{
+ fprintf(stderr, "%s: Operation not supported\n", __FUNCTION__);
+ return NULL;
+}
+
+void kvm_show_code(kvm_context_t kvm, int vcpu)
+{
+ fprintf(stderr, "%s: Operation not supported\n", __FUNCTION__);
+}
+
+void kvm_show_regs(kvm_context_t kvm, int vcpu)
+{
+ struct kvm_regs regs;
+ struct kvm_sregs sregs;
+ int i;
+
+ if (kvm_get_regs(kvm, vcpu, &regs))
+ return;
+
+ if (kvm_get_sregs(kvm, vcpu, &sregs))
+ return;
+
+ fprintf(stderr, "guest vcpu #%d\n", vcpu);
+ fprintf(stderr, "PSW:\t%16.16lx %16.16lx\n",
+ kvm->run[vcpu]->s390_sieic.mask,
+ kvm->run[vcpu]->s390_sieic.addr);
+ fprintf(stderr,"GPRS:");
+ for (i=0; i<15; i+=4)
+ fprintf(stderr, "\t%16.16lx %16.16lx %16.16lx %16.16lx\n",
+ regs.gprs[i],
+ regs.gprs[i+1],
+ regs.gprs[i+2],
+ regs.gprs[i+3]);
+ fprintf(stderr,"ACRS:");
+ for (i=0; i<15; i+=4)
+ fprintf(stderr, "\t%8.8x %8.8x %8.8x %8.8x\n",
+ sregs.acrs[i],
+ sregs.acrs[i+1],
+ sregs.acrs[i+2],
+ sregs.acrs[i+3]);
+
+ fprintf(stderr,"CRS:");
+ for (i=0; i<15; i+=4)
+ fprintf(stderr, "\t%16.16lx %16.16lx %16.16lx %16.16lx\n",
+ sregs.crs[i],
+ sregs.crs[i+1],
+ sregs.crs[i+2],
+ sregs.crs[i+3]);
+}
+
+int kvm_arch_create(kvm_context_t kvm, unsigned long phys_mem_bytes,
+ void **vm_mem)
+{
+ return 0;
+}
+
+int kvm_arch_create_default_phys_mem(kvm_context_t kvm,
+ unsigned long phys_mem_bytes,
+ void **vm_mem)
+{
+ return 0;
+}
+
+int kvm_arch_run(struct kvm_run *run, kvm_context_t kvm, int vcpu)
+{
+ int ret = 0;
+
+ switch (run->exit_reason){
+ default:
+ ret = 1;
+ break;
+ }
+ return ret;
+}
+
+int kvm_s390_initial_reset(kvm_context_t kvm, int slot)
+{
+ return ioctl(kvm->vcpu_fd[slot], KVM_S390_INITIAL_RESET, NULL);
+}
+
+int kvm_s390_interrupt(kvm_context_t kvm, int slot,
+ struct kvm_s390_interrupt *kvmint)
+{
+ if (slot>=0)
+ return ioctl(kvm->vcpu_fd[slot], KVM_S390_INTERRUPT, kvmint);
+ else
+ return ioctl(kvm->vm_fd, KVM_S390_INTERRUPT, kvmint);
+}
+
+int kvm_s390_set_initial_psw(kvm_context_t kvm, int slot, psw_t psw)
+{
+ return ioctl(kvm->vcpu_fd[slot], KVM_S390_SET_INITIAL_PSW, &psw);
+}
+
+int kvm_s390_store_status(kvm_context_t kvm, int slot, unsigned long addr)
+{
+ return ioctl(kvm->vcpu_fd[slot], KVM_S390_STORE_STATUS, addr);
+}
diff --git a/libkvm/libkvm.c b/libkvm/libkvm.c
index a49cbdc6..5edfad7c 100644
--- a/libkvm/libkvm.c
+++ b/libkvm/libkvm.c
@@ -48,6 +48,10 @@
#include "kvm-powerpc.h"
#endif
+#if defined(__s390__)
+#include "kvm-s390.h"
+#endif
+
int kvm_abi = EXPECTED_KVM_API_VERSION;
int kvm_page_size;
@@ -74,7 +78,7 @@ int get_free_slot(kvm_context_t kvm)
int i;
int tss_ext;
-#ifdef KVM_CAP_SET_TSS_ADDR
+#if defined(KVM_CAP_SET_TSS_ADDR) && !defined(__s390__)
tss_ext = ioctl(kvm->fd, KVM_CHECK_EXTENSION, KVM_CAP_SET_TSS_ADDR);
#else
tss_ext = 0;
@@ -410,7 +414,12 @@ void *kvm_create_userspace_phys_mem(kvm_context_t kvm, unsigned long phys_start,
if (writable)
prot |= PROT_WRITE;
+#if !defined(__s390__)
ptr = mmap(NULL, len, prot, MAP_ANONYMOUS | MAP_SHARED, -1, 0);
+#else
+ ptr = mmap(LIBKVM_S390_ORIGIN, len, prot | PROT_EXEC,
+ MAP_FIXED | MAP_SHARED | MAP_ANONYMOUS, -1, 0);
+#endif
if (ptr == MAP_FAILED) {
fprintf(stderr, "create_userspace_phys_mem: %s", strerror(errno));
return 0;
@@ -895,8 +904,10 @@ int kvm_run(kvm_context_t kvm, int vcpu)
struct kvm_run *run = kvm->run[vcpu];
again:
+#if !defined(__s390__)
if (!kvm->irqchip_in_kernel)
run->request_interrupt_window = try_push_interrupts(kvm);
+#endif
r = pre_kvm_run(kvm, vcpu);
if (r)
return r;
@@ -927,10 +938,12 @@ again:
}
#endif
+#if !defined(__s390__)
if (r == -1) {
r = handle_io_window(kvm);
goto more;
}
+#endif
if (1) {
switch (run->exit_reason) {
case KVM_EXIT_UNKNOWN:
@@ -969,6 +982,14 @@ again:
case KVM_EXIT_SHUTDOWN:
r = handle_shutdown(kvm, vcpu);
break;
+#if defined(__s390__)
+ case KVM_EXIT_S390_SIEIC:
+ r = kvm->callbacks->s390_handle_intercept(kvm, vcpu,
+ run);
+ break;
+ case KVM_EXIT_S390_RESET:
+ r = kvm->callbacks->s390_handle_reset(kvm, vcpu, run);
+#endif
default:
if (kvm_arch_run(run, kvm, vcpu)) {
fprintf(stderr, "unhandled vm exit: 0x%x\n",
diff --git a/libkvm/libkvm.h b/libkvm/libkvm.h
index ad6e26a7..9f06fcc3 100644
--- a/libkvm/libkvm.h
+++ b/libkvm/libkvm.h
@@ -5,6 +5,10 @@
#ifndef LIBKVM_H
#define LIBKVM_H
+#if defined(__s390__)
+#include <asm/ptrace.h>
+#endif
+
#include <stdint.h>
#ifndef __user
@@ -69,6 +73,12 @@ struct kvm_callbacks {
int (*powerpc_dcr_read)(int vcpu, uint32_t dcrn, uint32_t *data);
int (*powerpc_dcr_write)(int vcpu, uint32_t dcrn, uint32_t data);
#endif
+#if defined(__s390__)
+ int (*s390_handle_intercept)(kvm_context_t context, int vcpu,
+ struct kvm_run *run);
+ int (*s390_handle_reset)(kvm_context_t context, int vcpu,
+ struct kvm_run *run);
+#endif
};
/*!
@@ -639,4 +649,11 @@ int kvm_enable_vapic(kvm_context_t kvm, int vcpu, uint64_t vapic);
#endif
+#if defined(__s390__)
+int kvm_s390_initial_reset(kvm_context_t kvm, int slot);
+int kvm_s390_interrupt(kvm_context_t kvm, int slot,
+ struct kvm_s390_interrupt *kvmint);
+int kvm_s390_set_initial_psw(kvm_context_t kvm, int slot, psw_t psw);
+int kvm_s390_store_status(kvm_context_t kvm, int slot, unsigned long addr);
+#endif
#endif