diff options
author | Carsten Otte <cotte@de.ibm.com> | 2008-07-17 17:28:25 +0200 |
---|---|---|
committer | Avi Kivity <avi@qumranet.com> | 2008-07-19 10:56:07 +0300 |
commit | de3c8887aba71bc517404f6ac518656274bc534b (patch) | |
tree | 66100908294d018a7f2fc5ff3746cab29799e772 /libkvm | |
parent | 4773d38679d4e487dfd3db815eeb7e22278688f7 (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.mak | 3 | ||||
-rw-r--r-- | libkvm/config-s390x.mak | 3 | ||||
-rw-r--r-- | libkvm/kvm-common.h | 7 | ||||
-rw-r--r-- | libkvm/kvm-s390.h | 31 | ||||
-rw-r--r-- | libkvm/libkvm-s390.c | 131 | ||||
-rw-r--r-- | libkvm/libkvm.c | 23 | ||||
-rw-r--r-- | libkvm/libkvm.h | 17 |
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, ®s)) + 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 |