From patchwork Sat Mar 2 15:18:46 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sanjay Lal X-Patchwork-Id: 2207281 Return-Path: X-Original-To: patchwork-kvm@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork1.kernel.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by patchwork1.kernel.org (Postfix) with ESMTP id 02CF83FCF2 for ; Sat, 2 Mar 2013 15:20:18 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752804Ab3CBPUM (ORCPT ); Sat, 2 Mar 2013 10:20:12 -0500 Received: from kymasys.com ([64.62.140.43]:45476 "HELO kymasys.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with SMTP id S1752767Ab3CBPUL (ORCPT ); Sat, 2 Mar 2013 10:20:11 -0500 Received: from agni.kymasys.com ([75.40.23.192]) by kymasys.com for ; Sat, 2 Mar 2013 07:20:10 -0800 Received: by agni.kymasys.com (Postfix, from userid 500) id 1D78463005B; Sat, 2 Mar 2013 07:18:50 -0800 (PST) From: Sanjay Lal To: qemu-devel@nongnu.org Cc: kvm@vger.kernel.org, Aurelien Jarno , Gleb Natapov , Marcelo Tosatti , Sanjay Lal Subject: [Qemu-devel][PATCH 11/12] KVM/MIPS: MIPS specfic APIs for KVM. Date: Sat, 2 Mar 2013 07:18:46 -0800 Message-Id: <1362237527-23678-13-git-send-email-sanjayl@kymasys.com> X-Mailer: git-send-email 1.7.11.3 In-Reply-To: <1362237527-23678-1-git-send-email-sanjayl@kymasys.com> References: <1362237527-23678-1-git-send-email-sanjayl@kymasys.com> Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org --- target-mips/kvm.c | 292 +++++++++++++++++++++++++++++++++++++++++++++++++ target-mips/kvm_mips.h | 21 ++++ 2 files changed, 313 insertions(+) create mode 100644 target-mips/kvm.c create mode 100644 target-mips/kvm_mips.h diff --git a/target-mips/kvm.c b/target-mips/kvm.c new file mode 100644 index 0000000..7c01c76 --- /dev/null +++ b/target-mips/kvm.c @@ -0,0 +1,292 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * KVM/MIPS: MIPS specific KVM APIs + * + * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved. + * Authors: Sanjay Lal +*/ + +#include +#include +#include + +#include + +#include "qemu-common.h" +#include "qemu/timer.h" +#include "sysemu/sysemu.h" +#include "sysemu/kvm.h" +#include "cpu.h" +#include "sysemu/cpus.h" +#include "kvm_mips.h" + +//#define DEBUG_KVM + +#ifdef DEBUG_KVM +#define dprintf(fmt, ...) \ + do { fprintf(stderr, fmt, ## __VA_ARGS__); } while (0) +#else +#define dprintf(fmt, ...) \ + do { } while (0) +#endif + +extern int64_t g_kernel_entry; + + +const KVMCapabilityInfo kvm_arch_required_capabilities[] = { + KVM_CAP_LAST_INFO +}; + +unsigned long kvm_arch_vcpu_id(CPUState *cpu) +{ + return cpu->cpu_index; +} + +int kvm_arch_init(KVMState *s) +{ + dprintf("%s\n", __func__); + return 0; +} + +int kvm_arch_init_vcpu(CPUState *env) +{ + int ret = 0; + dprintf("%s\n", __func__); + return ret; +} + +void kvm_arch_reset_vcpu(CPUState *env) +{ + dprintf("%s\n", __func__); +#ifdef notyet + int ret; + + ret = kvm_vcpu_ioctl(env, KVM_NMI); + if (ret < 0) { + fprintf(stderr, "KVM: injection failed, NMI lost (%s)\n", + strerror(-ret)); + } +#endif +} + +int kvm_arch_put_registers(CPUState *cs, int level) +{ + MIPSCPU *cpu = MIPS_CPU(cs); + CPUMIPSState *env = &cpu->env; + struct kvm_regs regs; + int ret; + int i; + + /* Get the current register set as KVM seems it */ + ret = kvm_vcpu_ioctl(cs, KVM_GET_REGS, ®s); + if (ret < 0) + return ret; + + /* Now set the registers based on QEMU's view of things */ + for (i = 0;i < 32; i++) + regs.gprs[i] = env->active_tc.gpr[i]; + + regs.hi = env->active_tc.HI[0]; + regs.lo = env->active_tc.LO[0]; + regs.pc = env->active_tc.PC; + + regs.cp0reg[MIPS_CP0_TLB_INDEX][0] = env->CP0_Index; + regs.cp0reg[MIPS_CP0_TLB_CONTEXT][0] = env->CP0_Context; + regs.cp0reg[MIPS_CP0_BAD_VADDR][0] = env->CP0_BadVAddr; + regs.cp0reg[MIPS_CP0_TLB_HI][0] = env->CP0_EntryHi; + regs.cp0reg[MIPS_CP0_EXC_PC][0] = env->CP0_EPC; + + regs.cp0reg[MIPS_CP0_STATUS][0] = env->CP0_Status; + regs.cp0reg[MIPS_CP0_CAUSE][0] = env->CP0_Cause; + regs.cp0reg[MIPS_CP0_TLB_PG_MASK][0] = env->CP0_PageMask; + regs.cp0reg[MIPS_CP0_TLB_WIRED][0] = env->CP0_Wired; + + regs.cp0reg[MIPS_CP0_ERROR_PC][0] = env->CP0_ErrorEPC; + + ret = kvm_vcpu_ioctl(cs, KVM_SET_REGS, ®s); + + if (ret < 0) { + return ret; + } + + return ret; +} + +int kvm_arch_get_registers(CPUState *cs) +{ + MIPSCPU *cpu = MIPS_CPU(cs); + CPUMIPSState *env = &cpu->env; + int ret = 0; + struct kvm_regs regs; + int i; + + /* Get the current register set as KVM seems it */ + ret = kvm_vcpu_ioctl(cs, KVM_GET_REGS, ®s); + + if (ret < 0) + return ret; + + for (i = 0;i < 32; i++) + env->active_tc.gpr[i] = regs.gprs[i]; + + env->active_tc.HI[0] = regs.hi; + env->active_tc.LO[0] = regs.lo; + env->active_tc.PC = regs.pc; + + env->CP0_Index = regs.cp0reg[MIPS_CP0_TLB_INDEX][0]; + env->CP0_Context = regs.cp0reg[MIPS_CP0_TLB_CONTEXT][0]; + env->CP0_BadVAddr = regs.cp0reg[MIPS_CP0_BAD_VADDR][0]; + env->CP0_EntryHi = regs.cp0reg[MIPS_CP0_TLB_HI][0]; + env->CP0_EPC = regs.cp0reg[MIPS_CP0_EXC_PC][0]; + + env->CP0_Status = regs.cp0reg[MIPS_CP0_STATUS][0]; + env->CP0_Cause = regs.cp0reg[MIPS_CP0_CAUSE][0]; + env->CP0_PageMask = regs.cp0reg[MIPS_CP0_TLB_PG_MASK][0]; + env->CP0_Wired = regs.cp0reg[MIPS_CP0_TLB_WIRED][0]; + env->CP0_ErrorEPC= regs.cp0reg[MIPS_CP0_ERROR_PC][0]; + + return ret; +} + +int kvm_arch_insert_sw_breakpoint(CPUState *env, struct kvm_sw_breakpoint *bp) +{ + dprintf("%s\n", __func__); + return 0; +} + +int kvm_arch_remove_sw_breakpoint(CPUState *env, struct kvm_sw_breakpoint *bp) +{ + dprintf("%s\n", __func__); + return 0; +} + +static inline int cpu_mips_io_interrupts_pending(CPUArchState *env) +{ + dprintf("%s: %#x\n", __func__, env->CP0_Cause & (1 << (2 + CP0Ca_IP))); + return(env->CP0_Cause & (0x1 << (2 + CP0Ca_IP))); +} + + +void kvm_arch_pre_run(CPUState *cs, struct kvm_run *run) +{ + MIPSCPU *cpu = MIPS_CPU(cs); + CPUMIPSState *env = &cpu->env; + int r; + struct kvm_mips_interrupt intr; + + if (env->interrupt_request & CPU_INTERRUPT_HARD && + cpu_mips_io_interrupts_pending(env)) + { + intr.cpu = -1; + intr.irq = 2; + r = kvm_vcpu_ioctl(cs, KVM_INTERRUPT, &intr); + if (r < 0) + printf("cpu %d fail inject %x\n", cs->cpu_index, intr.irq); + } + /* If we have an interrupt but the guest is not ready to receive an + * interrupt, request an interrupt window exit. This will + * cause a return to userspace as soon as the guest is ready to + * receive interrupts. + */ + if ((env->interrupt_request & CPU_INTERRUPT_HARD)) { + run->request_interrupt_window = 1; + } else { + run->request_interrupt_window = 0; + } +} + +void kvm_arch_post_run(CPUState *env, struct kvm_run *run) +{ + dprintf("%s\n", __func__); +} + +int kvm_arch_process_async_events(CPUState *cs) +{ + MIPSCPU *cpu = MIPS_CPU(cs); + CPUMIPSState *env = &cpu->env; + + dprintf("%s\n", __func__); + return env->halted; +} + +int kvm_arch_handle_exit(CPUState *env, struct kvm_run *run) +{ + int ret; + + printf("kvm_arch_handle_exit()\n"); + switch (run->exit_reason) { + default: + fprintf(stderr, "KVM: unknown exit reason %d\n", run->exit_reason); + ret = -1; + break; + } + + return ret; +} + +bool kvm_arch_stop_on_emulation_error(CPUState *env) +{ + dprintf("%s\n", __func__); + return true; +} + +int kvm_arch_on_sigbus_vcpu(CPUState *env, int code, void *addr) +{ + dprintf("%s\n", __func__); + return 1; +} + +int kvm_arch_on_sigbus(int code, void *addr) +{ + dprintf("%s\n", __func__); + return 1; +} + +int kvm_mips_set_interrupt(CPUMIPSState *env, int irq, int level) +{ + CPUState *cs = ENV_GET_CPU(env); + struct kvm_mips_interrupt intr; + + if (!kvm_enabled()) { + return 0; + } + + intr.cpu = -1; + + if (level) + intr.irq = irq; + else + intr.irq = -irq; + + kvm_vcpu_ioctl(cs, KVM_INTERRUPT, &intr); + + return 0; +} + +int kvm_mips_set_ipi_interrupt(CPUArchState *env, int irq, int level) +{ + CPUState *cs = ENV_GET_CPU(cpu_single_env); + struct kvm_mips_interrupt intr; + + if (!kvm_enabled()) { + return 0; + } + + intr.cpu = cs->cpu_index; + + if (level) + intr.irq = irq; + else + intr.irq = -irq; + + dprintf("%s: CPU %d, IRQ: %d\n", __func__, intr.cpu, intr.irq); + + kvm_vcpu_ioctl(cs, KVM_INTERRUPT, &intr); + + return 0; +} + + diff --git a/target-mips/kvm_mips.h b/target-mips/kvm_mips.h new file mode 100644 index 0000000..20c3f8c --- /dev/null +++ b/target-mips/kvm_mips.h @@ -0,0 +1,21 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * KVM/MIPS: MIPS specific KVM APIs + * + * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved. + * Authors: Sanjay Lal +*/ + +#ifndef __KVM_MIPS_H__ +#define __KVM_MIPS_H__ + + +int kvm_mips_set_interrupt(CPUMIPSState *env, int irq, int level); + +int kvm_mips_set_ipi_interrupt(CPUArchState *env, int irq, int level); + + +#endif /* __KVM_MIPS_H__ */