On 06/03/2011 06:03 PM, Christoffer Dall wrote:
Targets KVM support for Cortex A-15 processors.

Contains no real functionality but all the framework components,
make files, header files and some tracing functionality.

+
+struct kvm_regs {
+       __u32 regs0_7[8];       /* Unbanked regs. (r0 - r7)        */
+       __u32 fiq_regs8_12[5];  /* Banked fiq regs. (r8 - r12)     */
+       __u32 usr_regs8_12[5];  /* Banked usr registers (r8 - r12) */
+       __u32 reg13[6];         /* Banked r13, indexed by MODE_    */
+       __u32 reg14[6];         /* Banked r13, indexed by MODE_    */
+       __u32 reg15;
+       __u32 cpsr;
+       __u32 spsr[5];          /* Banked SPSR,  indexed by MODE_  */
+       struct {
+               __u32 c2_base0;
+               __u32 c2_base1;
+               __u32 c3_dacr;
+       } cp15;
+
+};
+
+struct kvm_sregs {
+};
+
+struct kvm_fpu {
+};
+
+struct kvm_guest_debug_arch {
+};
+
+struct kvm_debug_exit_arch {
+};

Presumably, to be filled in later?

+
+/* Get vcpu register for current mode */
+#define vcpu_reg(_vcpu, _reg_num) \
+       (*kvm_vcpu_reg((_vcpu), _reg_num, vcpu_mode(_vcpu)))
+
+/* Get vcpu register for specific mode */
+#define vcpu_reg_m(_vcpu, _reg_num, _mode) \
+       (*kvm_vcpu_reg(_vcpu, _reg_num, _mode))
+
+#define vcpu_cpsr(_vcpu) \
+       (_vcpu->arch.regs.cpsr)
+
+/* Get vcpu SPSR for current mode */
+#define vcpu_spsr(_vcpu) \
+       kvm_vcpu_spsr(_vcpu, vcpu_mode(_vcpu))
+
+/* Get vcpu SPSR for specific mode */
+#define vcpu_spsr_m(_vcpu, _mode) \
+       kvm_vcpu_spsr(_vcpu, _mode)
+
+#define MODE_HAS_SPSR(_vcpu) \
+        ((vcpu_mode(_vcpu))<  MODE_USR)
+
+#define VCPU_MODE_PRIV(_vcpu) \
+       (((vcpu_mode(_vcpu)) == MODE_USR) ? 0 : 1)

Please use static inlines. Yes, you'll need more helpers to set registers, but it's worth it, especially as some macros evaluate an argument multiple times.

+if VIRTUALIZATION
+
+config KVM
+       bool "Kernel-based Virtual Machine (KVM) support"
+       select PREEMPT_NOTIFIERS
+       select ANON_INODES
+       select KVM_ARM_HOST
+       select KVM_MMIO
+       ---help---
+         Support hosting virtualized guest machines. You will also
+         need to select one or more of the processor modules below.
+
+         This module provides access to the hardware capabilities through
+         a character device node named /dev/kvm.
+
+         If unsure, say N.

I see you can't support a modular build, which is a pity.

+
+static int k_show(struct seq_file *m, void *v)
+{
+       print_kvm_debug_info(&seq_printf, m);
+       return 0;
+}
+
+static void *k_start(struct seq_file *m, loff_t *pos)
+{
+       return *pos<  1 ? (void *)1 : NULL;
+}
+
+static void *k_next(struct seq_file *m, void *v, loff_t *pos)
+{
+       ++*pos;
+       return NULL;
+}
+
+static void k_stop(struct seq_file *m, void *v)
+{
+}
+
+static const struct seq_operations kvmproc_op = {
+       .start  = k_start,
+       .next   = k_next,
+       .stop   = k_stop,
+       .show   = k_show
+};
+
+static int kvm_open(struct inode *inode, struct file *file)
+{
+       return seq_open(file,&kvmproc_op);
+}
+
+static const struct file_operations proc_kvm_operations = {
+       .open           = kvm_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = seq_release,
+};
+
+static int arm_init(void)
+{
+       int rc = kvm_init(NULL, sizeof(struct kvm_vcpu), 0, THIS_MODULE);
+       if (rc == 0)
+               proc_create("kvm", 0, NULL,&proc_kvm_operations);
+       return rc;
+}

/proc is frowned upon these days.  Is there no better place for this?+
+/*
+ * Return a pointer to the register number valid in the specified mode of
+ * the virtual CPU.
+ */
+u32* kvm_vcpu_reg(struct kvm_vcpu *vcpu, u8 reg_num, u32 mode)
+{
+       struct kvm_vcpu_regs *regs;
+       u8 reg_idx;
+       BUG_ON(reg_num>  15);
+
+       regs =&vcpu->arch.regs;
+
+       /* The PC is trivial */
+       if (reg_num == 15)
+               return&(regs->pc);
+
+       /* Non-banked registers */
+       if (reg_num<  8)
+               return&(regs->usr_regs[reg_num]);
+
+       /* Banked registers r13 and r14 */
+       if (reg_num>= 13) {
+               reg_idx = reg_num - 13; /* 0=r13 and 1=r14 */
+               switch (mode) {
+               case MODE_FIQ:
+                       return&(regs->fiq_regs[reg_idx + 5]);
+               case MODE_IRQ:
+                       return&(regs->irq_regs[reg_idx]);
+               case MODE_SVC:
+                       return&(regs->svc_regs[reg_idx]);
+               case MODE_ABT:
+                       return&(regs->abt_regs[reg_idx]);
+               case MODE_UND:
+                       return&(regs->und_regs[reg_idx]);
+               case MODE_USR:
+               case MODE_SYS:
+                       return&(regs->usr_regs[reg_idx]);
+               }
+       }
+
+       /* Banked FIQ registers r8-r12 */
+       if (reg_num>= 8&&  reg_num<= 12) {
+               if (mode == MODE_FIQ) {
+                       reg_idx = reg_num - 8; /* 0=r8, ..., 4=r12 */
+                       return&(regs->fiq_regs[reg_idx]);
+               } else
+                       return&(regs->usr_regs[reg_num]);
+       }

You could have a static 2D array indexed by mode and register number, returning an offsetof() into the vcpu structure.

+
+       BUG();
+       return NULL;
+}

diff --git a/arch/arm/kvm/trace.c b/arch/arm/kvm/trace.c
new file mode 100644
index 0000000..8ea1155
--- /dev/null
+++ b/arch/arm/kvm/trace.c
@@ -0,0 +1,436 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ */
+#include<linux/types.h>
+#include<linux/kvm_types.h>
+#include<linux/kvm_host.h>
+
+#include<asm/kvm_emulate.h>
+#include "trace.h"
+
+
+/******************************************************************************
+ * Simple event counting
+ */
+
+struct kvm_event {
+       unsigned long long cnt;
+       char *descr;
+};
+
+static struct kvm_event kvm_eventc_log[KVM_EVENTC_ITEMS] =
+{
+       { 0, "switch to guest" },
+       { 0, "exit from guest" },
+       { 0, "Block VCPU" },
+       { 0, "Exit to QEMU for IRQ window" },
+       { 0, "Switch VCPU mode" },
+       { 0, "VCPU IRQs on" },
+       { 0, "VCPU IRQs off" },
+       { 0, "Wait-for-interrupts" },
+       { 0, "Flush shadow page table" },
+       { 0, "Virtual TTBR change" },
+       { 0, "Read guest page table entry" },
+       { 0, "Map GVA to GFN" },
+       { 0, "Virtual DACR change" },
+       { 0, "VCPU switch to privileged mode" },
+       { 0, "VCPU switch from privileged mode" },
+       { 0, "VCPU process ID registers change" },
+       { 0, "Emulate Load/Store with translation" },
+       { 0, "Emulate MRS" },
+       { 0, "Emulate MSR" },
+       { 0, "Emulate CPS" },
+       { 0, "Need reschedule in execution loop" },
+       { 0, "MCR 7,  5, 0 - Invalidate entire I-cache" },
+       { 0, "MCR 7,  5, 1 - Invalidate line in I-cache MVA" },
+       { 0, "MCR 7,  5, 2 - Invalidate line in I-cache set/way" },
+       { 0, "MCR 7,  5, 7 - Flush branch target cache - MVA" },
+       { 0, "MCR 7,  6, 0 - Invalidate entire data cache" },
+       { 0, "MCR 7,  6, 1 - Invalidate data cache line - MVA" },
+       { 0, "MCR 7,  6, 2 - Invalidate data cache line - set/way" },
+       { 0, "MCR 7,  7, 0 - Invalidate D- and I-cache" },
+       { 0, "MCR 7, 10, 0 - Clean entire data cache" },
+       { 0, "MCR 7, 10, 1 - Clean data cache line - MVA" },
+       { 0, "MCR 7, 10, 4 - Data Synchronization Barrier (DSB)" },
+       { 0, "MCR 7, 14, 0 - Clean and invalidate entire D-cache" },
+       { 0, "MCR 7, 14, 1 - Clean and invalidate D-cache line - MVA" },
+       { 0, "MCR 7, 15, 0 - Clean and invalidate unified cache" },
+       { 0, "MCR 8,  5, 0 - Invalidate instruction TLB" },
+       { 0, "MCR 8,  6, 0 - Invalidate data TLB" },
+       { 0, "MCR 8,  7, 0 - Invalidate unified TLB" },
+       { 0, "Emulate Load-Store multiple" },
+};
+
+void kvm_arm_count_event(unsigned int event)
+{
+       if (event>= KVM_EVENTC_ITEMS)
+               return;
+
+       kvm_eventc_log[event].cnt++;
+}

We've switched to ftrace for this sort of thing. Simply add a tracepoint for each interesting event, and the kernel can provide you with

- a count of events ('perf stat')
- a log of events ('trace-cmd record/report'), possibly with other kernel events interspersed
- a running histogram ('kvm_stat')

with near-zero impact when disabled.

See include/trace/events/kvm.h, arch/x86/kvm/trace.h.

--
error compiling committee.c: too many arguments to function

--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to