aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSanjay Lal <sanjayl@kymasys.com>2012-11-21 18:34:03 -0800
committerRalf Baechle <ralf@linux-mips.org>2013-05-08 03:55:35 +0200
commit9843b030cc951bce4a4d9bec38b5155c96eb1740 (patch)
treedd219e76dce1e1b92e6f5fc19e8767b60827c7ee
parent669e846e6c4e13f16d7418973609931e362cb16a (diff)
KVM/MIPS32: KVM Guest kernel support.
Both Guest kernel and Guest Userspace execute in UM. The memory map is as follows: Guest User address space: 0x00000000 -> 0x40000000 Guest Kernel Unmapped: 0x40000000 -> 0x60000000 Guest Kernel Mapped: 0x60000000 -> 0x80000000 - Guest Usermode virtual memory is limited to 1GB. Signed-off-by: Sanjay Lal <sanjayl@kymasys.com> Cc: kvm@vger.kernel.org Cc: linux-mips@linux-mips.org Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
-rw-r--r--arch/mips/include/asm/mach-generic/spaces.h9
-rw-r--r--arch/mips/include/asm/processor.h5
-rw-r--r--arch/mips/include/asm/uaccess.h11
-rw-r--r--arch/mips/kernel/binfmt_elfo32.c4
-rw-r--r--arch/mips/kernel/cevt-r4k.c4
-rw-r--r--arch/mips/kernel/traps.c7
-rw-r--r--arch/mips/mti-malta/malta-time.c15
7 files changed, 52 insertions, 3 deletions
diff --git a/arch/mips/include/asm/mach-generic/spaces.h b/arch/mips/include/asm/mach-generic/spaces.h
index 73d717a..5b2f2e6 100644
--- a/arch/mips/include/asm/mach-generic/spaces.h
+++ b/arch/mips/include/asm/mach-generic/spaces.h
@@ -20,14 +20,21 @@
#endif
#ifdef CONFIG_32BIT
-
+#ifdef CONFIG_KVM_GUEST
+#define CAC_BASE _AC(0x40000000, UL)
+#else
#define CAC_BASE _AC(0x80000000, UL)
+#endif
#define IO_BASE _AC(0xa0000000, UL)
#define UNCAC_BASE _AC(0xa0000000, UL)
#ifndef MAP_BASE
+#ifdef CONFIG_KVM_GUEST
+#define MAP_BASE _AC(0x60000000, UL)
+#else
#define MAP_BASE _AC(0xc0000000, UL)
#endif
+#endif
/*
* Memory above this physical address will be considered highmem.
diff --git a/arch/mips/include/asm/processor.h b/arch/mips/include/asm/processor.h
index 2a5fa7a..71686c8 100644
--- a/arch/mips/include/asm/processor.h
+++ b/arch/mips/include/asm/processor.h
@@ -44,11 +44,16 @@ extern unsigned int vced_count, vcei_count;
#define SPECIAL_PAGES_SIZE PAGE_SIZE
#ifdef CONFIG_32BIT
+#ifdef CONFIG_KVM_GUEST
+/* User space process size is limited to 1GB in KVM Guest Mode */
+#define TASK_SIZE 0x3fff8000UL
+#else
/*
* User space process size: 2GB. This is hardcoded into a few places,
* so don't change it unless you know what you are doing.
*/
#define TASK_SIZE 0x7fff8000UL
+#endif
#ifdef __KERNEL__
#define STACK_TOP_MAX TASK_SIZE
diff --git a/arch/mips/include/asm/uaccess.h b/arch/mips/include/asm/uaccess.h
index bd87e36..b46caab 100644
--- a/arch/mips/include/asm/uaccess.h
+++ b/arch/mips/include/asm/uaccess.h
@@ -23,7 +23,11 @@
*/
#ifdef CONFIG_32BIT
-#define __UA_LIMIT 0x80000000UL
+#ifdef CONFIG_KVM_GUEST
+#define __UA_LIMIT 0x40000000UL
+#else
+#define __UA_LIMIT 0x80000000UL
+#endif
#define __UA_ADDR ".word"
#define __UA_LA "la"
@@ -55,8 +59,13 @@ extern u64 __ua_limit;
* address in this range it's the process's problem, not ours :-)
*/
+#ifdef CONFIG_KVM_GUEST
+#define KERNEL_DS ((mm_segment_t) { 0x80000000UL })
+#define USER_DS ((mm_segment_t) { 0xC0000000UL })
+#else
#define KERNEL_DS ((mm_segment_t) { 0UL })
#define USER_DS ((mm_segment_t) { __UA_LIMIT })
+#endif
#define VERIFY_READ 0
#define VERIFY_WRITE 1
diff --git a/arch/mips/kernel/binfmt_elfo32.c b/arch/mips/kernel/binfmt_elfo32.c
index 556a435..97c5a16 100644
--- a/arch/mips/kernel/binfmt_elfo32.c
+++ b/arch/mips/kernel/binfmt_elfo32.c
@@ -48,7 +48,11 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG];
__res; \
})
+#ifdef CONFIG_KVM_GUEST
+#define TASK32_SIZE 0x3fff8000UL
+#else
#define TASK32_SIZE 0x7fff8000UL
+#endif
#undef ELF_ET_DYN_BASE
#define ELF_ET_DYN_BASE (TASK32_SIZE / 3 * 2)
diff --git a/arch/mips/kernel/cevt-r4k.c b/arch/mips/kernel/cevt-r4k.c
index 07b847d..fd75d71 100644
--- a/arch/mips/kernel/cevt-r4k.c
+++ b/arch/mips/kernel/cevt-r4k.c
@@ -118,6 +118,10 @@ int c0_compare_int_usable(void)
unsigned int delta;
unsigned int cnt;
+#ifdef CONFIG_KVM_GUEST
+ return 1;
+#endif
+
/*
* IP7 already pending? Try to clear it by acking the timer.
*/
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index a200b5b..59351e5 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -1713,7 +1713,12 @@ void __init trap_init(void)
ebase = (unsigned long)
__alloc_bootmem(size, 1 << fls(size), 0);
} else {
- ebase = CKSEG0;
+#ifdef CONFIG_KVM_GUEST
+#define KVM_GUEST_KSEG0 0x40000000
+ ebase = KVM_GUEST_KSEG0;
+#else
+ ebase = CKSEG0;
+#endif
if (cpu_has_mips_r2)
ebase += (read_c0_ebase() & 0x3ffff000);
}
diff --git a/arch/mips/mti-malta/malta-time.c b/arch/mips/mti-malta/malta-time.c
index a144b89..bc6ac00 100644
--- a/arch/mips/mti-malta/malta-time.c
+++ b/arch/mips/mti-malta/malta-time.c
@@ -76,6 +76,21 @@ static void __init estimate_frequencies(void)
unsigned int count, start;
unsigned int giccount = 0, gicstart = 0;
+#if defined (CONFIG_KVM_GUEST) && defined (CONFIG_KVM_HOST_FREQ)
+ unsigned int prid = read_c0_prid() & 0xffff00;
+
+ /*
+ * XXXKYMA: hardwire the CPU frequency to Host Freq/4
+ */
+ count = (CONFIG_KVM_HOST_FREQ * 1000000) >> 3;
+ if ((prid != (PRID_COMP_MIPS | PRID_IMP_20KC)) &&
+ (prid != (PRID_COMP_MIPS | PRID_IMP_25KF)))
+ count *= 2;
+
+ mips_hpt_frequency = count;
+ return;
+#endif
+
local_irq_save(flags);
/* Start counter exactly on falling edge of update flag. */