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 majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html