[Qemu-devel] [PATCH] kvm: sync cpu state on internal error before dump
When a KVM internal error occurs QEMU dumps the CPU state, however it doesn't synchronise the state from KVM first so the dumped state is out of date. Add the synchronisation calls before the dump in both locations (which is used depends on whether the arch says to stop or not). Note that x86 does a sync in its kvm_arch_stop_on_emulation_error() function so at least for emulation errors is unaffected. Signed-off-by: James Hogan Cc: Gleb Natapov Cc: Paolo Bonzini Cc: k...@vger.kernel.org --- kvm-all.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/kvm-all.c b/kvm-all.c index b788fcd..803141a 100644 --- a/kvm-all.c +++ b/kvm-all.c @@ -1546,6 +1546,7 @@ static int kvm_handle_internal_error(CPUState *cpu, struct kvm_run *run) if (run->internal.suberror == KVM_INTERNAL_ERROR_EMULATION) { fprintf(stderr, "emulation failure\n"); if (!kvm_arch_stop_on_emulation_error(cpu)) { +kvm_cpu_synchronize_state(cpu); cpu_dump_state(cpu, stderr, fprintf, CPU_DUMP_CODE); return EXCP_INTERRUPT; } @@ -1701,6 +1702,7 @@ int kvm_cpu_exec(CPUState *cpu) } while (ret == 0); if (ret < 0) { +kvm_cpu_synchronize_state(cpu); cpu_dump_state(cpu, stderr, fprintf, CPU_DUMP_CODE); vm_stop(RUN_STATE_INTERNAL_ERROR); } -- 1.8.1.2
Re: [Qemu-devel] [PATCH] kvm: sync cpu state on internal error before dump
On 23/08/13 13:58, Gleb Natapov wrote: > On Fri, Aug 23, 2013 at 01:26:00PM +0100, James Hogan wrote: >> When a KVM internal error occurs QEMU dumps the CPU state, however it >> doesn't synchronise the state from KVM first so the dumped state is out >> of date. Add the synchronisation calls before the dump in both locations >> (which is used depends on whether the arch says to stop or not). >> > x86_cpu_dump_state() calls cpu_synchronize_state() already. Ah yes, thanks. I hadn't noticed that. Out of the arches that support KVM only x86 and ppc call it. arm, mips (qemu support not upstream yet), and s390 don't. s390 never seems to emit that exit code, and arm only does so for unsupported exceptions (which should never happen). I'll fix in mips_cpu_dump_state() instead. Cheers James
Re: [Qemu-devel] [PATCH] mips/malta: prevent writes to reset flash mapping faulting
Hi Andreas, On 23/08/13 12:08, Andreas Färber wrote: > Am 23.08.2013 09:59, schrieb Leon Alrae: >> From: James Hogan >> >> Commit a427338 (mips_malta: correct reading MIPS revision at 0x1fc00010) >> altered the behaviour of the monitor flash mapping at the reset address >> by making it read only. However this causes data bus error exceptions >> when it is written to since it is effectively unassigned memory for >> writes. This isn't how the real hardware behaves. That memory can be >> written to (even with the MFWR jumper not fitted) and the new value read >> back from, but it doesn't get written back to the monitor flash so is >> volatile. >> >> This is fixed by converting the bios copy from read only ram to a bios >> device with a nop write callback. > > That sounds like a contradiction: The nop write will not have reads > return the new value, will it? correct. > Why not just remove the _set_readonly and have it reloaded on reset for > volatility? That's what I tried first, but the bios copy is normal ram so it doesn't get reloaded on reset. I'll have a play to see if I can use rom_add_blob (although I seem to remember already trying that...). > Anyway, having a MemoryRegionOps with just a .write looks dangerous, but > I guess you've tested read to work. We had been seeing assertions > elsewhere when either was missing. Yeh reads seem to work fine (it also executes from it fine). Thanks for taking a look James
[Qemu-devel] [PATCH v2] cpu: Move cpu state syncs up into cpu_dump_state()
The x86 and ppc targets call cpu_synchronize_state() from their *_cpu_dump_state() callbacks to ensure that up to date state is dumped when KVM is enabled (for example when a KVM internal error occurs). Move this call up into the generic cpu_dump_state() function so that other KVM targets (namely MIPS) can take advantage of it. This requires kvm_cpu_synchronize_state() and cpu_synchronize_state() to be moved out of the #ifdef NEED_CPU_H in so that they're accessible to qom/cpu.c. Signed-off-by: James Hogan Cc: Andreas Färber Cc: Alexander Graf Cc: Gleb Natapov Cc: qemu-...@nongnu.org Cc: k...@vger.kernel.org --- Changes in v2 (was kvm: sync cpu state on internal error before dump) - rewrite to fix in cpu_dump_state() (Gleb Natapov) --- include/sysemu/kvm.h | 20 ++-- qom/cpu.c | 1 + target-i386/helper.c | 2 -- target-ppc/translate.c | 2 -- 4 files changed, 11 insertions(+), 14 deletions(-) diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h index de74411..71a0186 100644 --- a/include/sysemu/kvm.h +++ b/include/sysemu/kvm.h @@ -270,16 +270,6 @@ int kvm_check_extension(KVMState *s, unsigned int extension); uint32_t kvm_arch_get_supported_cpuid(KVMState *env, uint32_t function, uint32_t index, int reg); -void kvm_cpu_synchronize_state(CPUState *cpu); - -/* generic hooks - to be moved/refactored once there are more users */ - -static inline void cpu_synchronize_state(CPUState *cpu) -{ -if (kvm_enabled()) { -kvm_cpu_synchronize_state(cpu); -} -} #if !defined(CONFIG_USER_ONLY) int kvm_physical_memory_addr_from_host(KVMState *s, void *ram_addr, @@ -288,9 +278,19 @@ int kvm_physical_memory_addr_from_host(KVMState *s, void *ram_addr, #endif /* NEED_CPU_H */ +void kvm_cpu_synchronize_state(CPUState *cpu); void kvm_cpu_synchronize_post_reset(CPUState *cpu); void kvm_cpu_synchronize_post_init(CPUState *cpu); +/* generic hooks - to be moved/refactored once there are more users */ + +static inline void cpu_synchronize_state(CPUState *cpu) +{ +if (kvm_enabled()) { +kvm_cpu_synchronize_state(cpu); +} +} + static inline void cpu_synchronize_post_reset(CPUState *cpu) { if (kvm_enabled()) { diff --git a/qom/cpu.c b/qom/cpu.c index aa95108..cfe7e24 100644 --- a/qom/cpu.c +++ b/qom/cpu.c @@ -174,6 +174,7 @@ void cpu_dump_state(CPUState *cpu, FILE *f, fprintf_function cpu_fprintf, CPUClass *cc = CPU_GET_CLASS(cpu); if (cc->dump_state) { +cpu_synchronize_state(cpu); cc->dump_state(cpu, f, cpu_fprintf, flags); } } diff --git a/target-i386/helper.c b/target-i386/helper.c index bf3e2ac..2aecfd0 100644 --- a/target-i386/helper.c +++ b/target-i386/helper.c @@ -188,8 +188,6 @@ void x86_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf, char cc_op_name[32]; static const char *seg_name[6] = { "ES", "CS", "SS", "DS", "FS", "GS" }; -cpu_synchronize_state(cs); - eflags = cpu_compute_eflags(env); #ifdef TARGET_X86_64 if (env->hflags & HF_CS64_MASK) { diff --git a/target-ppc/translate.c b/target-ppc/translate.c index f07d70d..c6a6ff8 100644 --- a/target-ppc/translate.c +++ b/target-ppc/translate.c @@ -9536,8 +9536,6 @@ void ppc_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf, CPUPPCState *env = &cpu->env; int i; -cpu_synchronize_state(cs); - cpu_fprintf(f, "NIP " TARGET_FMT_lx " LR " TARGET_FMT_lx " CTR " TARGET_FMT_lx " XER " TARGET_FMT_lx "\n", env->nip, env->lr, env->ctr, cpu_read_xer(env)); -- 1.8.1.2
[Qemu-devel] [PATCH] qemu: Fix cross compilation for mipsel
The configure script was setting HOST_WORDS_BIGENDIAN for all $cpu = mips|mips64 when cross compiling, since endianness cannot be detected by running a test program. This includes little endian MIPS though. It didn't cause any build errors but does prevent QEMU from working correctly. Instead, detect the endianness similar to how we do for ARM, by checking for the __MIPSEB__ builtin processor definition. This is from a hunk in the "[PATCH 8/12] KVM/MIPS: Enable KVM/MIPS for MIPS targets. Add MIPS GIC code to the build" patch by Sanjay Lal [1]. [1] https://patchwork.kernel.org/patch/2207251/ Signed-off-by: James Hogan Cc: Andreas Färber Cc: Sanjay Lal Cc: qemu-sta...@nongnu.org --- configure | 7 ++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/configure b/configure index 0a55c20..a765a9f 100755 --- a/configure +++ b/configure @@ -1415,7 +1415,12 @@ case "$cpu" in bigendian=yes fi ;; - hppa|m68k|mips|mips64|ppc|ppc64|s390|s390x|sparc|sparc64) + mips|mips64) +if check_define __MIPSEB__; then + bigendian=yes +fi + ;; + hppa|m68k|ppc|ppc64|s390|s390x|sparc|sparc64) bigendian=yes ;; esac -- 1.8.1.2
Re: [Qemu-devel] [PATCH] configure: detect endian via compile test
On 1 July 2013 04:30, Mike Frysinger wrote: > This avoids needing to execute a program and keeping an (incomplete) > list when cross-compiling. > > Signed-off-by: Mike Frysinger This fixes mipsel cross compiling. I also checked it detected a mips (be) compiler as big endian. Tested-by: James Hogan [mips] Can somebody please apply this. Maybe for stable too? Cheers James
Re: [Qemu-devel] [PATCH] qemu: Fix cross compilation for mipsel
On 27/08/13 19:39, Richard Henderson wrote: > On 08/27/2013 09:02 AM, James Hogan wrote: >> The configure script was setting HOST_WORDS_BIGENDIAN for all $cpu = >> mips|mips64 when cross compiling, since endianness cannot be detected by >> running a test program. This includes little endian MIPS though. It >> didn't cause any build errors but does prevent QEMU from working >> correctly. Instead, detect the endianness similar to how we do for ARM, >> by checking for the __MIPSEB__ builtin processor definition. >> >> This is from a hunk in the "[PATCH 8/12] KVM/MIPS: Enable KVM/MIPS for >> MIPS targets. Add MIPS GIC code to the build" patch by Sanjay Lal [1]. > > Redundant with Mike Frysinger's more general patch, > > http://patchwork.ozlabs.org/patch/256001/ Even better. Thanks for pointing that out. I've added my tested-by. Cheers James
Re: [Qemu-devel] [PATCH] target-mips: fix get_physical_address() #if 0 build error
On 27/08/13 20:48, Richard Henderson wrote: > On 08/27/2013 09:48 AM, Yongbok Kim wrote: >> #if 0 >> -qemu_log(TARGET_FMT_lx " %d %d => " TARGET_FMT_lx " %d (%d)\n", >> +qemu_log(TARGET_FMT_lx " %d %d => %" HWADDR_PRIx " %d (%d)\n", >> address, rw, access_type, *physical, *prot, ret); >> #endif > > While by itself correct, consider converting this to the trace infrastructure > (with uint64_t instead of hwaddr). > > If it's not worth a trace, it's probably not worth keeping at all. True. I suspect it isn't worth a trace (I just happened to be modifying that function so tried it out to test my changes - and anybody doing that can easily add a temporary qemu_log/fprintf message themselves). Cheers James
Re: [Qemu-devel] [PATCH v3 03/21] target-mips: add SELEQZ and SELNEZ instructions
Hi Leon, On 27/06/14 16:21, Leon Alrae wrote: > /* MIPS64 MIPS-3D ASE support. */ > #define I16 INSN_MIPS16 > @@ -1209,6 +1215,8 @@ const struct mips_opcode mips_builtin_opcodes[] = > them first. The assemblers uses a hash table based on the > instruction name anyhow. */ > /* name,args,match, mask, pinfo, > membership */ > +{"seleqz", "d,v,t",0x0035, 0xfc0007ff, WR_d|RD_s|RD_t, 0, > I32R6}, > +{"selnez", "d,v,t",0x0037, 0xfc0007ff, WR_d|RD_s|RD_t, 0, > I32R6}, I don't think these need to be at the beginning of the table since they're normal instructions, unlike "nop" for example which is encoded as a "sll". Otherwise Reviewed-by: James Hogan Cheers James
Re: [Qemu-devel] [PATCH v3 03/21] target-mips: add SELEQZ and SELNEZ instructions
Hi Leon, On 27/06/14 16:21, Leon Alrae wrote: > diff --git a/target-mips/translate.c b/target-mips/translate.c > index 931a580..bb95f7b 100644 > --- a/target-mips/translate.c > +++ b/target-mips/translate.c > @@ -189,6 +189,9 @@ enum { > OPC_MOVZ = 0x0A | OPC_SPECIAL, > OPC_MOVN = 0x0B | OPC_SPECIAL, > > +OPC_SELEQZ = 0x35 | OPC_SPECIAL, > +OPC_SELNEZ = 0x37 | OPC_SPECIAL, > + > OPC_MOVCI= 0x01 | OPC_SPECIAL, > > /* Special */ maybe it makes sense to remove OPC_SPECIAL35_RESERVED and OPC_SPECIAL37_RESERVED now too. Cheers James
Re: [Qemu-devel] [PATCH v3 04/21] target-mips: move LL and SC instructions
Hi Leon, On 27/06/14 16:21, Leon Alrae wrote: > @@ -1215,6 +1217,8 @@ const struct mips_opcode mips_builtin_opcodes[] = > them first. The assemblers uses a hash table based on the > instruction name anyhow. */ > /* name,args,match, mask, pinfo, > membership */ > +{"ll", "t,o(b)", 0x7c36, 0xfc3f, LDD|RD_b|WR_t,0, > I32R6}, > +{"sc", "t,o(b)", 0x7c26, 0xfc3f, LDD|RD_b|WR_t,0, > I32R6}, Doesn't bit 6 need to be 0 too for these, so mask should be 0xfc7f? Again, do these strictly have to be at the beginning? I know sc aliases dmod.g, but that's right at the end of the table. > @@ -15121,7 +15144,8 @@ static void decode_opc (CPUMIPSState *env, > DisasContext *ctx) > break; > case OPC_DDIV_G_2E ... OPC_DDIVU_G_2E: > case OPC_DMULT_G_2E ... OPC_DMULTU_G_2E: > -case OPC_DMOD_G_2E ... OPC_DMODU_G_2E: > +case OPC_DMODU_G_2E: > +check_insn_opc_removed(ctx, ISA_MIPS32R6); AFAICT you remove this check_insn_opc_removed line again in patch 6, so I don't think you need to add it here. Otherwise Reviewed-by: James Hogan Cheers James
Re: [Qemu-devel] [PATCH v3 03/21] target-mips: add SELEQZ and SELNEZ instructions
On 26/09/14 13:45, Leon Alrae wrote: > Hi James, > > On 26/09/2014 13:03, James Hogan wrote: >> Hi Leon, >> >> On 27/06/14 16:21, Leon Alrae wrote: >>> /* MIPS64 MIPS-3D ASE support. */ >>> #define I16 INSN_MIPS16 >>> @@ -1209,6 +1215,8 @@ const struct mips_opcode mips_builtin_opcodes[] = >>> them first. The assemblers uses a hash table based on the >>> instruction name anyhow. */ >>> /* name,args, match, mask, pinfo, >>> membership */ >>> +{"seleqz", "d,v,t",0x0035, 0xfc0007ff, WR_d|RD_s|RD_t, 0, >>> I32R6}, >>> +{"selnez", "d,v,t",0x0037, 0xfc0007ff, WR_d|RD_s|RD_t, 0, >>> I32R6}, >> >> I don't think these need to be at the beginning of the table since >> they're normal instructions, unlike "nop" for example which is encoded >> as a "sll". > > I don't have any preference on this, just wanted to have new R6 > instructions grouped. As I can see in binutils new R6 instructions were > placed at the bottom so I could stick to it as well. It just seems like most of them are alphabetical in the main group, the few at the top before "abs" seem to be specifically aliases of other instructions, and the other groups at the bottom are there for specific reasons too by the looks of it. It's not my code though so if others are fine with it, so be it. Cheers James
[Qemu-devel] [PATCH v5 07/12] target-mips: kvm: Add main KVM support for MIPS
From: Sanjay Lal Implement the main KVM arch API for MIPS. Signed-off-by: Sanjay Lal Signed-off-by: James Hogan Cc: Aurelien Jarno Cc: Gleb Natapov Cc: Paolo Bonzini Cc: Andreas Färber Cc: Peter Maydell --- Changes in v5: - Rename kvm_arch_reset_vcpu to kvm_mips_reset_vcpu based on commit 50a2c6e55fa2 (kvm: reset state from the CPU's reset method). - Rename kvm_mips_te_{put,get}_cp0_registers() functions to drop the "te_" since they're not really specific to T&E. - Pass level through from kvm_arch_put_registers() to kvm_mips_put_cp0_registers() rather than hard coding it to KVM_PUT_FULL_STATE. - Fix KVM_REG_MIPS_CP0_* definitions to set KVM_REG_MIPS and KVM_REG_SIZE_U32/KVM_REG_SIZE_U64 (using a macro). - Remove unused KVM_REG_MIPS_CP0_* definitions for now. - Correct type of kvm_mips_{get,put}_one_{,ul}reg() reg_id argument to uint64_t. Various high bits must be set to disambiguate the architecture and register size. - Add register accessors for always-64-bit registers (rather than ulong registers). These are needed for virtual KVM registers for controlling the KVM Compare/Count timer. - Simplify register access functions slightly. - Save and restore KVM timer state with the rest of the state, and also when VM clock is started or stopped. When the KVM timer state is restored (or VM clock restarted) it is resumed with the stored count at the monotonic time when the VM clock was last stopped. If the VM clock hasn't been stopped it resumes from the monotonic time when the state was saved (i.e. as if the timer was never stopped). Changes since RFC patch on kernel KVM thread "[PATCH v2 00/23] MIPS: KVM: Fixes and guest timer rewrite"): - Simplified, removing extra state for storing VM time of save/restore, at the cost of losing/gaining time when VM gets stopped and started (Paolo Bonzini). - Save and restore the UserLocal and HWREna CP0 registers. - Improve get/put KVM register error handling with DPRINTFs and fall through so that getting/putting of all the registers is attempted even if one of them fails due to being unimplemented in the kernel. Changes in v4: (No functional changes, assembly output unchanged) - Use int32_t instead of int32 (which is for softfloat) in kvm register accessors (Andreas Färber). - Use uint64_t instead of __u64 (which is really just for kernel headers) in the kvm register accessors (Andreas Färber). - Cast pointer to uintptr_t rather than target_ulong in kvm register accessors. - Remove some redundant casts in kvm register accessors. Changes in v3: - s/dprintf/DPRINTF/ (Andreas Färber). - Use "cs" rather than "cpu" or "env" for CPUState variable names (Andreas Färber). - Use CPUMIPSState rather than CPUArchState (Andreas Färber). - Pass MIPSCPU to cpu_mips_io_interrupts_pending() rather than CPUMIPSState (Andreas Färber). - Remove spurious parentheses around cpu_mips_io_interrupts_pending() call (Andreas Färber). - Pass MIPSCPU to kvm_mips_set_[ipi_]interrupt (Andreas Färber). - Make use of error_report (Andreas Färber) and clean up error messages a little to include __func__. - Remove inline kvm_mips_{put,get}_one_[ul]reg() declarations from kvm_mips.h. They're only used in target-mips/kvm.c anyway. - Make kvm_arch_{put,get}_registers static within target-mips/kvm.c and remove from kvm_mips.h. - Set sigmask length to 16 from kvm_arch_init() since MIPS Linux has 128 signals. This is better than cluttering kvm_all.c with TARGET_* ifdefs (Peter Maydell). Changes in v2: - Expand commit message - Checkpatch cleanups. - Some interrupt bug fixes from Yann Le Du - Add get/set register functionality from Yann Le Du - Use new 64 bit compatible ABI from Cavium from Sanjay Lal - Add dummy kvm_arch_init_irq_routing() The common KVM code insists on calling kvm_arch_init_irq_routing() as soon as it sees kernel header support for it (regardless of whether QEMU supports it). Provide a dummy function to satisfy this. - Remove request_interrupt_window code (Peter Maydell) --- target-mips/kvm.c | 683 + target-mips/kvm_mips.h | 26 ++ 2 files changed, 709 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 ..844e5bbe5f92 --- /dev/null +++ b/target-mips/kvm.c @@ -0,0 +1,683 @@ +/* + * 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-2014 Imagination Technologies Ltd. + * Authors: Sanjay Lal +*/ + +#include +#include +#include + +#include + +#include "qemu-comm
[Qemu-devel] [PATCH v5 02/12] hw/mips/cputimer: Don't start periodic timer in KVM mode
From: Sanjay Lal Compare/Count timer interrupts are handled in-kernel for KVM. Therefore don't bother creating the timer at init time if KVM is enabled. This will conveniently avoid attempts to set the timeout when cpu_mips_store_count() is called at reset with KVM enabled, treating the timer as stopped so that CP0_Count is modified directly. Signed-off-by: Sanjay Lal [james.ho...@imgtec.com: Update after "target-mips: Reset CPU timer consistently" which moves timer start to reset time] Signed-off-by: James Hogan Cc: Aurelien Jarno Cc: Paolo Bonzini --- Changes in v5: - Update commit message and comment in cpu_mips_clock_init() after the patch "target-mips: Reset CPU timer consistently") (Paolo Bonzini). Changes in v2: - Expand commit message - Rebase on v1.7.0 - Wrap comment --- hw/mips/cputimer.c | 9 - 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/hw/mips/cputimer.c b/hw/mips/cputimer.c index 6900a745c60c..577c9aeab877 100644 --- a/hw/mips/cputimer.c +++ b/hw/mips/cputimer.c @@ -23,6 +23,7 @@ #include "hw/hw.h" #include "hw/mips/cpudevs.h" #include "qemu/timer.h" +#include "sysemu/kvm.h" #define TIMER_FREQ 100 * 1000 * 1000 @@ -146,5 +147,11 @@ static void mips_timer_cb (void *opaque) void cpu_mips_clock_init (CPUMIPSState *env) { -env->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, &mips_timer_cb, env); +/* + * If we're in KVM mode, don't create the periodic timer, that is handled in + * kernel. + */ +if (!kvm_enabled()) { +env->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, &mips_timer_cb, env); +} } -- 1.9.3
[Qemu-devel] [PATCH v5 03/12] hw/mips: Add API to convert KVM guest KSEG0 <-> GPA
From: Sanjay Lal Add API for converting physical addresses to KVM guest KSEG0 addresses, and fix the existing API for converting KSEG0 addresses to physical addresses to work in the KVM case. Both have the same sized KSEG0, so it's just a case of fixing the mask. In KVM trap and emulate mode both the guest kernel and guest userspace execute in useg: Guest User address space: 0x..0x3fff Guest Kernel Unmapped: 0x4000..0x5fff Guest Kernel Mapped:0x6000..0x7fff Signed-off-by: Sanjay Lal Signed-off-by: James Hogan Cc: Aurelien Jarno --- Changes in v5: - KSEG0 doesn't actually change size, so fix mask in cpu_mips_kseg0_to_phys() instead of having the KVM specific cpu_mips_kvm_um_kseg0_to_phys(). Changes in v2: - Expand commit message - Remove unnecessary include --- hw/mips/addr.c| 7 ++- include/hw/mips/cpudevs.h | 2 ++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/hw/mips/addr.c b/hw/mips/addr.c index 99488f1d2a6f..ff3b952600bb 100644 --- a/hw/mips/addr.c +++ b/hw/mips/addr.c @@ -25,10 +25,15 @@ uint64_t cpu_mips_kseg0_to_phys(void *opaque, uint64_t addr) { -return addr & 0x7fffll; +return addr & 0x1fffll; } uint64_t cpu_mips_phys_to_kseg0(void *opaque, uint64_t addr) { return addr | ~0x7fffll; } + +uint64_t cpu_mips_kvm_um_phys_to_kseg0(void *opaque, uint64_t addr) +{ +return addr | 0x4000ll; +} diff --git a/include/hw/mips/cpudevs.h b/include/hw/mips/cpudevs.h index 6bea24bf102d..b2626f2922f4 100644 --- a/include/hw/mips/cpudevs.h +++ b/include/hw/mips/cpudevs.h @@ -5,6 +5,8 @@ /* mips_addr.c */ uint64_t cpu_mips_kseg0_to_phys(void *opaque, uint64_t addr); uint64_t cpu_mips_phys_to_kseg0(void *opaque, uint64_t addr); +uint64_t cpu_mips_kvm_um_phys_to_kseg0(void *opaque, uint64_t addr); + /* mips_int.c */ void cpu_mips_irq_init_cpu(CPUMIPSState *env); -- 1.9.3
[Qemu-devel] [PATCH v5 08/12] target-mips: Call kvm_mips_reset_vcpu() from mips_cpu_reset()
When KVM is enabled call kvm_mips_reset_vcpu() from mips_cpu_reset() as done for other targets since commit 50a2c6e55fa2 (kvm: reset state from the CPU's reset method). Signed-off-by: James Hogan Cc: Aurelien Jarno Cc: Paolo Bonzini Cc: Gleb Natapov --- Changes in v5: - New patch, based on commit 50a2c6e55fa2 (kvm: reset state from the CPU's reset method). --- target-mips/cpu.c | 8 1 file changed, 8 insertions(+) diff --git a/target-mips/cpu.c b/target-mips/cpu.c index dd954fc55a10..b3e0e6cce7b6 100644 --- a/target-mips/cpu.c +++ b/target-mips/cpu.c @@ -19,7 +19,9 @@ */ #include "cpu.h" +#include "kvm_mips.h" #include "qemu-common.h" +#include "sysemu/kvm.h" static void mips_cpu_set_pc(CPUState *cs, vaddr value) @@ -87,6 +89,12 @@ static void mips_cpu_reset(CPUState *s) tlb_flush(s, 1); cpu_state_reset(env); + +#ifndef CONFIG_USER_ONLY +if (kvm_enabled()) { +kvm_mips_reset_vcpu(cpu); +} +#endif } static void mips_cpu_realizefn(DeviceState *dev, Error **errp) -- 1.9.3
[Qemu-devel] [PATCH v5 01/12] target-mips: Reset CPU timer consistently
The MIPS CPU timer (CP0 Count/Compare registers & QEMU timer) is reset at machine initialisation, including starting the timeout. Both registers however are placed before mvp in CPUMIPSState so they will both be zeroed on reset by the memset in mips_cpu_reset() including soon after init. This doesn't take into account that the timer may be running, in which case env->CP0_Count will represent the delta against the VM clock and the timeout will need updating. At init time (cpu_mips_clock_init()), lets only create the timer. Setting Count = 1 and starting the timer (cpu_mips_store_count()) can be done at reset time from cpu_state_reset(), which is after the memset. There is also no need to set CP0_Compare = 0 as that is already handled by the memset. Note that a reset occurs from mips_cpu_realizefn() which is before the machine init callback has had a chance to set up the CPU interrupts and the CPU timer, so env->timer will be NULL. This case is handled explicitly in cpu_mips_store_count(), treating the timer as disabled (which will also be the right thing to do when KVM support is added). Reported-by: Paolo Bonzini Signed-off-by: James Hogan Cc: Aurelien Jarno --- Changes in v5: - New patch (Paolo Bonzini). --- hw/mips/cputimer.c | 9 ++--- target-mips/translate.c | 2 ++ 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/hw/mips/cputimer.c b/hw/mips/cputimer.c index c8b4b000cd0e..6900a745c60c 100644 --- a/hw/mips/cputimer.c +++ b/hw/mips/cputimer.c @@ -85,7 +85,12 @@ uint32_t cpu_mips_get_count (CPUMIPSState *env) void cpu_mips_store_count (CPUMIPSState *env, uint32_t count) { -if (env->CP0_Cause & (1 << CP0Ca_DC)) +/* + * This gets called from cpu_state_reset(), potentially before timer init. + * So env->timer may be NULL, which is also the case with KVM enabled so + * treat timer as disabled in that case. + */ +if (env->CP0_Cause & (1 << CP0Ca_DC) || !env->timer) env->CP0_Count = count; else { /* Store new count register */ @@ -142,6 +147,4 @@ static void mips_timer_cb (void *opaque) void cpu_mips_clock_init (CPUMIPSState *env) { env->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, &mips_timer_cb, env); -env->CP0_Compare = 0; -cpu_mips_store_count(env, 1); } diff --git a/target-mips/translate.c b/target-mips/translate.c index 2c4c80103d14..b63f30fc3a76 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -16091,6 +16091,8 @@ void cpu_state_reset(CPUMIPSState *env) /* Count register increments in debug mode, EJTAG version 1 */ env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER); +cpu_mips_store_count(env, 1); + if (env->CP0_Config3 & (1 << CP0C3_MT)) { int i; -- 1.9.3
[Qemu-devel] [PATCH v5 11/12] target-mips: Enable KVM support in build system
From: Sanjay Lal Enable KVM support for MIPS in the build system. Signed-off-by: Sanjay Lal Signed-off-by: James Hogan Reviewed-by: Aurelien Jarno --- Changes in v2: - Expand commit message - Remove GIC code - Create asm-mips symlink using generic code and move above default case (Peter Maydell) - Remove redundant check of target_name = cpu = mips - Remove mipsel cross compilation fix, which is now fixed by commit 61cc919f73ea (configure: detect endian via compile test) --- configure | 6 +- target-mips/Makefile.objs | 1 + 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/configure b/configure index 27d84d9fdbe4..a32e651aa421 100755 --- a/configure +++ b/configure @@ -4830,6 +4830,9 @@ if test "$linux" = "yes" ; then aarch64) linux_arch=arm64 ;; + mips64) +linux_arch=mips +;; *) # For most CPUs the kernel architecture name and QEMU CPU name match. linux_arch="$cpu" @@ -5028,7 +5031,7 @@ case "$target_name" in *) esac case "$target_name" in - aarch64|arm|i386|x86_64|ppcemb|ppc|ppc64|s390x) + aarch64|arm|i386|x86_64|ppcemb|ppc|ppc64|s390x|mipsel|mips) # Make sure the target and host cpus are compatible if test "$kvm" = "yes" -a "$target_softmmu" = "yes" -a \ \( "$target_name" = "$cpu" -o \ @@ -5036,6 +5039,7 @@ case "$target_name" in \( "$target_name" = "ppc64" -a "$cpu" = "ppc" \) -o \ \( "$target_name" = "ppc"-a "$cpu" = "ppc64" \) -o \ \( "$target_name" = "ppcemb" -a "$cpu" = "ppc64" \) -o \ + \( "$target_name" = "mipsel" -a "$cpu" = "mips" \) -o \ \( "$target_name" = "x86_64" -a "$cpu" = "i386" \) -o \ \( "$target_name" = "i386" -a "$cpu" = "x86_64" \) \) ; then echo "CONFIG_KVM=y" >> $config_target_mak diff --git a/target-mips/Makefile.objs b/target-mips/Makefile.objs index 0277d56e8252..716244f3d5f3 100644 --- a/target-mips/Makefile.objs +++ b/target-mips/Makefile.objs @@ -1,3 +1,4 @@ obj-y += translate.o dsp_helper.o op_helper.o lmi_helper.o helper.o cpu.o obj-y += gdbstub.o obj-$(CONFIG_SOFTMMU) += machine.o +obj-$(CONFIG_KVM) += kvm.o -- 1.9.3
[Qemu-devel] [PATCH v5 05/12] target-mips: get_physical_address: Add KVM awareness
MIPS KVM trap & emulate mode (which is currently the only supported mode) has to add an extra kseg0/kseg1 at 0x4000 and an extra kseg2/kseg3 at 0x6000. Take this into account in get_physical_address() so that debug memory access works. This is done by translating the address to a standard kseg0 or kseg2 address before doing the normal address translation. The real virtual address is still used for TLB lookups. Signed-off-by: James Hogan Cc: Aurelien Jarno --- target-mips/helper.c | 33 ++--- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/target-mips/helper.c b/target-mips/helper.c index caacd762fd90..8a997e44e5ac 100644 --- a/target-mips/helper.c +++ b/target-mips/helper.c @@ -24,6 +24,7 @@ #include #include "cpu.h" +#include "sysemu/kvm.h" enum { TLBRET_DIRTY = -4, @@ -100,7 +101,7 @@ int r4k_map_address (CPUMIPSState *env, hwaddr *physical, int *prot, } static int get_physical_address (CPUMIPSState *env, hwaddr *physical, -int *prot, target_ulong address, +int *prot, target_ulong real_address, int rw, int access_type) { /* User mode can only access useg/xuseg */ @@ -113,6 +114,8 @@ static int get_physical_address (CPUMIPSState *env, hwaddr *physical, int KX = (env->CP0_Status & (1 << CP0St_KX)) != 0; #endif int ret = TLBRET_MATCH; +/* effective address (modified for KVM T&E kernel segments) */ +target_ulong address = real_address; #if 0 qemu_log("user mode %d h %08x\n", user_mode, env->hflags); @@ -124,19 +127,35 @@ static int get_physical_address (CPUMIPSState *env, hwaddr *physical, #define KSEG2_BASE 0xC000UL #define KSEG3_BASE 0xE000UL +#define KVM_KSEG0_BASE 0x4000UL +#define KVM_KSEG2_BASE 0x6000UL + +if (kvm_enabled()) { +/* KVM T&E adds guest kernel segments in useg */ +if (real_address >= KVM_KSEG0_BASE) { +if (real_address < KVM_KSEG2_BASE) { +/* kseg0 */ +address += KSEG0_BASE - KVM_KSEG0_BASE; +} else if (real_address <= USEG_LIMIT) { +/* kseg2/3 */ +address += KSEG2_BASE - KVM_KSEG2_BASE; +} +} +} + if (address <= USEG_LIMIT) { /* useg */ if (env->CP0_Status & (1 << CP0St_ERL)) { *physical = address & 0x; *prot = PAGE_READ | PAGE_WRITE; } else { -ret = env->tlb->map_address(env, physical, prot, address, rw, access_type); +ret = env->tlb->map_address(env, physical, prot, real_address, rw, access_type); } #if defined(TARGET_MIPS64) } else if (address < 0x4000ULL) { /* xuseg */ if (UX && address <= (0x3FFFULL & env->SEGMask)) { -ret = env->tlb->map_address(env, physical, prot, address, rw, access_type); +ret = env->tlb->map_address(env, physical, prot, real_address, rw, access_type); } else { ret = TLBRET_BADADDR; } @@ -144,7 +163,7 @@ static int get_physical_address (CPUMIPSState *env, hwaddr *physical, /* xsseg */ if ((supervisor_mode || kernel_mode) && SX && address <= (0x7FFFULL & env->SEGMask)) { -ret = env->tlb->map_address(env, physical, prot, address, rw, access_type); +ret = env->tlb->map_address(env, physical, prot, real_address, rw, access_type); } else { ret = TLBRET_BADADDR; } @@ -161,7 +180,7 @@ static int get_physical_address (CPUMIPSState *env, hwaddr *physical, /* xkseg */ if (kernel_mode && KX && address <= (0x7FFFULL & env->SEGMask)) { -ret = env->tlb->map_address(env, physical, prot, address, rw, access_type); +ret = env->tlb->map_address(env, physical, prot, real_address, rw, access_type); } else { ret = TLBRET_BADADDR; } @@ -185,7 +204,7 @@ static int get_physical_address (CPUMIPSState *env, hwaddr *physical, } else if (address < (int32_t)KSEG3_BASE) { /* sseg (kseg2) */ if (supervisor_mode || kernel_mode) { -ret = env->tlb->map_address(env, physical, prot, address, rw, access_type); +ret = env->tlb->map_address(env, physical, prot, real_address, rw, access_type); } else { ret = TLBRET_BADADDR; } @@ -193,7 +212,7 @@ static int get_physical_address (CPUMIPSState *env, hwaddr *physical, /* kseg3 */ /* XXX: debug segment is not emulated */ if (kernel_mode) { -
[Qemu-devel] [PATCH v5 06/12] kvm: Allow arch to set sigmask length
MIPS/Linux is unusual in having 128 signals rather than just 64 like most other architectures. This means its sigmask is 16 bytes instead of 8, so allow arches to override the sigmask->len value passed to the KVM_SET_SIGNAL_MASK ioctl in kvm_set_signal_mask() by calling kvm_set_sigmask_len() from kvm_arch_init(). Otherwise default to 8 bytes. Signed-off-by: James Hogan Cc: Aurelien Jarno Cc: Sanjay Lal Cc: Gleb Natapov Cc: Paolo Bonzini Cc: Peter Maydell --- Changes in v3: - Rewrote to allow sigmask length to be set by kvm_arch_init(), so that MIPS can set it to 16 as it has 128 signals. This is better than cluttering kvm-all.c with TARGET_* ifdefs (Peter Maydell). Changes in v2: - Expand commit message - Reword comment --- include/sysemu/kvm.h | 2 ++ kvm-all.c| 11 ++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h index e79e92c50e3f..de4bdaa40e56 100644 --- a/include/sysemu/kvm.h +++ b/include/sysemu/kvm.h @@ -325,6 +325,8 @@ int kvm_check_extension(KVMState *s, unsigned int extension); uint32_t kvm_arch_get_supported_cpuid(KVMState *env, uint32_t function, uint32_t index, int reg); +void kvm_set_sigmask_len(KVMState *s, unsigned int sigmask_len); + #if !defined(CONFIG_USER_ONLY) int kvm_physical_memory_addr_from_host(KVMState *s, void *ram_addr, hwaddr *phys_addr); diff --git a/kvm-all.c b/kvm-all.c index 4e19eff0efee..0d485b644539 100644 --- a/kvm-all.c +++ b/kvm-all.c @@ -99,6 +99,7 @@ struct KVMState * they're not. Linux, glibc and *BSD all treat ioctl numbers as * unsigned, and treating them as signed here can break things */ unsigned irq_set_ioctl; +unsigned int sigmask_len; #ifdef KVM_CAP_IRQ_ROUTING struct kvm_irq_routing *irq_routes; int nr_allocated_irq_routes; @@ -1397,6 +1398,8 @@ int kvm_init(MachineClass *mc) assert(TARGET_PAGE_SIZE <= getpagesize()); page_size_init(); +s->sigmask_len = 8; + #ifdef KVM_CAP_SET_GUEST_DEBUG QTAILQ_INIT(&s->kvm_sw_breakpoints); #endif @@ -1575,6 +1578,11 @@ err: return ret; } +void kvm_set_sigmask_len(KVMState *s, unsigned int sigmask_len) +{ +s->sigmask_len = sigmask_len; +} + static void kvm_handle_io(uint16_t port, void *data, int direction, int size, uint32_t count) { @@ -2095,6 +2103,7 @@ void kvm_remove_all_breakpoints(CPUState *cpu) int kvm_set_signal_mask(CPUState *cpu, const sigset_t *sigset) { +KVMState *s = kvm_state; struct kvm_signal_mask *sigmask; int r; @@ -2104,7 +2113,7 @@ int kvm_set_signal_mask(CPUState *cpu, const sigset_t *sigset) sigmask = g_malloc(sizeof(*sigmask) + sizeof(*sigset)); -sigmask->len = 8; +sigmask->len = s->sigmask_len; memcpy(sigmask->sigset, sigset, sizeof(*sigset)); r = kvm_vcpu_ioctl(cpu, KVM_SET_SIGNAL_MASK, sigmask); g_free(sigmask); -- 1.9.3
[Qemu-devel] [PATCH v5 10/12] hw/mips: malta: Add KVM support
In KVM mode the bootrom is loaded and executed from the last 1MB of DRAM. Based on "[PATCH 12/12] KVM/MIPS: General KVM support and support for SMP Guests" by Sanjay Lal . Signed-off-by: James Hogan Reviewed-by: Aurelien Jarno Cc: Peter Maydell Cc: Sanjay Lal --- Changes in v5: - Kseg0 doesn't actually change size, so use cpu_mips_kseg0_to_phys() rather than having the KVM specific cpu_mips_kvm_um_kseg0_to_phys(). Changes in v3: - Remove unnecessary includes, especially linux/kvm.h which isn't a good idea on non-Linux (Peter Maydell). Changes in v2: - Removal of cps / GIC / SMP support - Minimal bootloader modified to execute safely from RAM - Remove "Writing bootloader to final 1MB of RAM" printf --- hw/mips/mips_malta.c | 73 ++-- 1 file changed, 53 insertions(+), 20 deletions(-) diff --git a/hw/mips/mips_malta.c b/hw/mips/mips_malta.c index f4a7d4712952..8bc5392b4223 100644 --- a/hw/mips/mips_malta.c +++ b/hw/mips/mips_malta.c @@ -51,6 +51,7 @@ #include "sysemu/qtest.h" #include "qemu/error-report.h" #include "hw/empty_slot.h" +#include "sysemu/kvm.h" //#define DEBUG_BOARD_INIT @@ -603,29 +604,31 @@ static void network_init(PCIBus *pci_bus) */ static void write_bootloader (CPUMIPSState *env, uint8_t *base, - int64_t kernel_entry) + int64_t run_addr, int64_t kernel_entry) { uint32_t *p; /* Small bootloader */ p = (uint32_t *)base; -stl_p(p++, 0x0bf00160); /* j 0x1fc00580 */ + +stl_p(p++, 0x0800 | /* j 0x1fc00580 */ + ((run_addr + 0x580) & 0x0fff) >> 2); stl_p(p++, 0x); /* nop */ /* YAMON service vector */ -stl_p(base + 0x500, 0xbfc00580); /* start: */ -stl_p(base + 0x504, 0xbfc0083c); /* print_count: */ -stl_p(base + 0x520, 0xbfc00580); /* start: */ -stl_p(base + 0x52c, 0xbfc00800); /* flush_cache: */ -stl_p(base + 0x534, 0xbfc00808); /* print: */ -stl_p(base + 0x538, 0xbfc00800); /* reg_cpu_isr: */ -stl_p(base + 0x53c, 0xbfc00800); /* unred_cpu_isr: */ -stl_p(base + 0x540, 0xbfc00800); /* reg_ic_isr: */ -stl_p(base + 0x544, 0xbfc00800); /* unred_ic_isr: */ -stl_p(base + 0x548, 0xbfc00800); /* reg_esr: */ -stl_p(base + 0x54c, 0xbfc00800); /* unreg_esr: */ -stl_p(base + 0x550, 0xbfc00800); /* getchar: */ -stl_p(base + 0x554, 0xbfc00800); /* syscon_read: */ +stl_p(base + 0x500, run_addr + 0x0580); /* start: */ +stl_p(base + 0x504, run_addr + 0x083c); /* print_count: */ +stl_p(base + 0x520, run_addr + 0x0580); /* start: */ +stl_p(base + 0x52c, run_addr + 0x0800); /* flush_cache: */ +stl_p(base + 0x534, run_addr + 0x0808); /* print: */ +stl_p(base + 0x538, run_addr + 0x0800); /* reg_cpu_isr: */ +stl_p(base + 0x53c, run_addr + 0x0800); /* unred_cpu_isr: */ +stl_p(base + 0x540, run_addr + 0x0800); /* reg_ic_isr: */ +stl_p(base + 0x544, run_addr + 0x0800); /* unred_ic_isr: */ +stl_p(base + 0x548, run_addr + 0x0800); /* reg_esr: */ +stl_p(base + 0x54c, run_addr + 0x0800); /* unreg_esr: */ +stl_p(base + 0x550, run_addr + 0x0800); /* getchar: */ +stl_p(base + 0x554, run_addr + 0x0800); /* syscon_read: */ /* Second part of the bootloader */ @@ -701,7 +704,7 @@ static void write_bootloader (CPUMIPSState *env, uint8_t *base, p = (uint32_t *) (base + 0x800); stl_p(p++, 0x03e8); /* jr ra */ stl_p(p++, 0x2402); /* li v0,0 */ - /* 808 YAMON print */ +/* 808 YAMON print */ stl_p(p++, 0x03e06821); /* move t5,ra */ stl_p(p++, 0x00805821); /* move t3,a0 */ stl_p(p++, 0x00a05021); /* move t2,a1 */ @@ -774,6 +777,7 @@ static int64_t load_kernel (void) uint32_t *prom_buf; long prom_size; int prom_index = 0; +uint64_t (*xlate_to_kseg0) (void *opaque, uint64_t addr); #ifdef TARGET_WORDS_BIGENDIAN big_endian = 1; @@ -788,6 +792,11 @@ static int64_t load_kernel (void) loaderparams.kernel_filename); exit(1); } +if (kvm_enabled()) { +xlate_to_kseg0 = cpu_mips_kvm_um_phys_to_kseg0; +} else { +xlate_to_kseg0 = cpu_mips_phys_to_kseg0; +} /* load initrd */ initrd_size = 0; @@ -820,7 +829,7 @@ static int64_t load_kernel (void) prom_set(prom_buf, prom_index++, "%s", loaderparams.kernel_filename); if (initrd_size > 0) { prom_set(prom_buf, prom_ind
[Qemu-devel] [PATCH v5 09/12] hw/mips: In KVM mode, inject IRQ2 (I/O) interrupts via ioctls
From: Sanjay Lal COP0 emulation is in-kernel for KVM, so inject IRQ2 (I/O) interrupts via ioctls. Signed-off-by: Sanjay Lal Signed-off-by: James Hogan Reviewed-by: Aurelien Jarno Reviewed-by: Andreas Färber --- Changes in v5: - Fix typo in subject (s/interupts/interrupts/) Changes in v3: - Pass MIPSCPU to kvm_mips_set_[ipi_]interrupt (Andreas Färber). Changes in v2: - Expand commit message - Remove #ifdef CONFIG_KVM since it's guarded by kvm_enabled() already --- hw/mips/mips_int.c | 11 +++ 1 file changed, 11 insertions(+) diff --git a/hw/mips/mips_int.c b/hw/mips/mips_int.c index 7dbd24d3d6e5..d740046ba151 100644 --- a/hw/mips/mips_int.c +++ b/hw/mips/mips_int.c @@ -23,6 +23,8 @@ #include "hw/hw.h" #include "hw/mips/cpudevs.h" #include "cpu.h" +#include "sysemu/kvm.h" +#include "kvm_mips.h" static void cpu_mips_irq_request(void *opaque, int irq, int level) { @@ -35,8 +37,17 @@ static void cpu_mips_irq_request(void *opaque, int irq, int level) if (level) { env->CP0_Cause |= 1 << (irq + CP0Ca_IP); + +if (kvm_enabled() && irq == 2) { +kvm_mips_set_interrupt(cpu, irq, level); +} + } else { env->CP0_Cause &= ~(1 << (irq + CP0Ca_IP)); + +if (kvm_enabled() && irq == 2) { +kvm_mips_set_interrupt(cpu, irq, level); +} } if (env->CP0_Cause & CP0Ca_IP_mask) { -- 1.9.3
[Qemu-devel] [PATCH v5 04/12] target-mips: get_physical_address: Add defines for segment bases
Add preprocessor definitions for 32bit segment bases for use in get_physical_address(). These will also be taken advantage of in the next patch which adds KVM awareness. Signed-off-by: James Hogan Reviewed-by: Aurelien Jarno --- target-mips/helper.c | 18 -- 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/target-mips/helper.c b/target-mips/helper.c index 064622cc31ba..caacd762fd90 100644 --- a/target-mips/helper.c +++ b/target-mips/helper.c @@ -118,7 +118,13 @@ static int get_physical_address (CPUMIPSState *env, hwaddr *physical, qemu_log("user mode %d h %08x\n", user_mode, env->hflags); #endif -if (address <= (int32_t)0x7FFFUL) { +#define USEG_LIMIT 0x7FFFUL +#define KSEG0_BASE 0x8000UL +#define KSEG1_BASE 0xA000UL +#define KSEG2_BASE 0xC000UL +#define KSEG3_BASE 0xE000UL + +if (address <= USEG_LIMIT) { /* useg */ if (env->CP0_Status & (1 << CP0St_ERL)) { *physical = address & 0x; @@ -160,23 +166,23 @@ static int get_physical_address (CPUMIPSState *env, hwaddr *physical, ret = TLBRET_BADADDR; } #endif -} else if (address < (int32_t)0xA000UL) { +} else if (address < (int32_t)KSEG1_BASE) { /* kseg0 */ if (kernel_mode) { -*physical = address - (int32_t)0x8000UL; +*physical = address - (int32_t)KSEG0_BASE; *prot = PAGE_READ | PAGE_WRITE; } else { ret = TLBRET_BADADDR; } -} else if (address < (int32_t)0xC000UL) { +} else if (address < (int32_t)KSEG2_BASE) { /* kseg1 */ if (kernel_mode) { -*physical = address - (int32_t)0xA000UL; +*physical = address - (int32_t)KSEG1_BASE; *prot = PAGE_READ | PAGE_WRITE; } else { ret = TLBRET_BADADDR; } -} else if (address < (int32_t)0xE000UL) { +} else if (address < (int32_t)KSEG3_BASE) { /* sseg (kseg2) */ if (supervisor_mode || kernel_mode) { ret = env->tlb->map_address(env, physical, prot, address, rw, access_type); -- 1.9.3
[Qemu-devel] [PATCH v5 12/12] MAINTAINERS: Add entry for MIPS KVM
Add MAINTAINERS entry for MIPS KVM. Signed-off-by: James Hogan --- Changes in v4: - Add MAINTAINERS entry for MIPS KVM. --- MAINTAINERS | 5 + 1 file changed, 5 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 51a6f51842be..0a637c90c679 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -176,6 +176,11 @@ M: Peter Maydell S: Maintained F: target-arm/kvm.c +MIPS +M: James Hogan +S: Maintained +F: target-mips/kvm.c + PPC M: Alexander Graf S: Maintained -- 1.9.3
[Qemu-devel] [PATCH v5 00/12] KVM Support for MIPS32 Processors
m/00README.txt alludes to anyway). - Rewrote kvm sigmask patch to allow sigmask length to be set by kvm_arch_init(), so that MIPS can set it to 16 as it has 128 signals. This is better than cluttering kvm-all.c with TARGET_* ifdefs (Peter Maydell). - Set sigmask length to 16 from kvm_arch_init() since MIPS Linux has 128 signals. This is better than cluttering kvm_all.c with TARGET_* ifdefs (Peter Maydell). - s/dprintf/DPRINTF/ (Andreas Färber). - Use "cs" rather than "cpu" or "env" for CPUState variable names (Andreas Färber). - Use CPUMIPSState rather than CPUArchState (Andreas Färber). - Pass MIPSCPU to cpu_mips_io_interrupts_pending() rather than CPUMIPSState (Andreas Färber). - Remove spurious parentheses around cpu_mips_io_interrupts_pending() call (Andreas Färber). - Pass MIPSCPU to kvm_mips_set_[ipi_]interrupt (Andreas Färber). - Make use of error_report (Andreas Färber) and clean up error messages a little to include __func__. - Remove inline kvm_mips_{put,get}_one_[ul]reg() declarations from kvm_mips.h. They're only used in target-mips/kvm.c anyway. - Make kvm_arch_{put,get}_registers static within target-mips/kvm.c and remove from kvm_mips.h. - Remove unnecessary includes from Malta patch, especially linux/kvm.h which isn't a good idea on non-Linux (Peter Maydell). Changes in v2: This patchset is based on Sanjay Lal's V1 patchset from 2nd March 2013: https://patchwork.kernel.org/project/kvm/list/?submitter=51991&state=*&q=qemu-devel I think I've addressed all the V1 feedback. The other main change is the removal of the boot-CPS ROM code binary blob and GIC/SMP support since it's all slightly orthogonal to KVM support. Instead the existing minimal bootloader code for Malta has been updated to work with KVM T&E. A git tag for this version of the patchset can also be found on github: https://github.com/jahogan/qemu-kvm-mips.git kvm-mips-v2 - Expand commit messages - Rebase on v1.7.0 - Misc checkpatch and other cleanups - Some interrupt bug fixes from Yann Le Du - Add get/set register functionality from Yann Le Du - Use new 64 bit compatible ABI from Cavium from Sanjay Lal - Add dummy kvm_arch_init_irq_routing() The common KVM code insists on calling kvm_arch_init_irq_routing() as soon as it sees kernel header support for it (regardless of whether QEMU supports it). Provide a dummy function to satisfy this. - Remove request_interrupt_window code (Peter Maydell) - Remove #ifdef CONFIG_KVM where guarded by kvm_enabled() already - Removal of cps / GIC / SMP support - Minimal bootloader modified to execute safely from RAM - Create asm-mips symlink using generic code and move above default case (Peter Maydell) - Remove redundant check of target_name = cpu = mips - Remove mipsel cross compilation fix, which is now fixed by commit 61cc919f73ea (configure: detect endian via compile test) - Add translation of guest kernel segments to allow an attached gdb to see kernel memory correctly James Hogan (7): target-mips: Reset CPU timer consistently target-mips: get_physical_address: Add defines for segment bases target-mips: get_physical_address: Add KVM awareness kvm: Allow arch to set sigmask length target-mips: Call kvm_mips_reset_vcpu() from mips_cpu_reset() hw/mips: malta: Add KVM support MAINTAINERS: Add entry for MIPS KVM Sanjay Lal (5): hw/mips/cputimer: Don't start periodic timer in KVM mode hw/mips: Add API to convert KVM guest KSEG0 <-> GPA target-mips: kvm: Add main KVM support for MIPS hw/mips: In KVM mode, inject IRQ2 (I/O) interrupts via ioctls target-mips: Enable KVM support in build system MAINTAINERS | 5 + configure | 6 +- hw/mips/addr.c| 7 +- hw/mips/cputimer.c| 18 +- hw/mips/mips_int.c| 11 + hw/mips/mips_malta.c | 73 +++-- include/hw/mips/cpudevs.h | 2 + include/sysemu/kvm.h | 2 + kvm-all.c | 11 +- target-mips/Makefile.objs | 1 + target-mips/cpu.c | 8 + target-mips/helper.c | 51 +++- target-mips/kvm.c | 683 ++ target-mips/kvm_mips.h| 26 ++ target-mips/translate.c | 2 + 15 files changed, 866 insertions(+), 40 deletions(-) create mode 100644 target-mips/kvm.c create mode 100644 target-mips/kvm_mips.h -- 1.9.3
[Qemu-devel] [PATCH v2] hw/mips: gt64xxx_pci: Add VMStateDescription
From: Sanjay Lal Add VMStateDescription for GT64120 PCI emulation used by the Malta platform, to allow it to work with savevm/loadvm and live migration. Signed-off-by: Sanjay Lal [james.ho...@imgtec.com: Convert to VMState] Signed-off-by: James Hogan Cc: Aurelien Jarno --- This is based on "[Patch 03/12] KVM/MIPS: Add save/restore state APIs for saving/restoring KVM guests."[1]. Changes in v2: - Expand commit message - Convert to VMState (Peter Maydell) [1] https://lists.gnu.org/archive/html/qemu-devel/2013-03/msg00195.html --- hw/mips/gt64xxx_pci.c | 152 ++ 1 file changed, 152 insertions(+) diff --git a/hw/mips/gt64xxx_pci.c b/hw/mips/gt64xxx_pci.c index 6398514c99d2..76690ecd6ca4 100644 --- a/hw/mips/gt64xxx_pci.c +++ b/hw/mips/gt64xxx_pci.c @@ -312,6 +312,156 @@ static void gt64120_pci_mapping(GT64120State *s) } } +static int gt64120_post_load(void *opaque, int version_id) +{ +GT64120State *s = opaque; + +gt64120_isd_mapping(s); +gt64120_pci_mapping(s); + +return 0; +} + +static const VMStateDescription vmstate_gt64120 = { +.name = "gt64120", +.version_id = 1, +.minimum_version_id = 1, +.post_load = gt64120_post_load, +.fields = (VMStateField[]) { +/* CPU Configuration */ +VMSTATE_UINT32(regs[GT_CPU], GT64120State), +VMSTATE_UINT32(regs[GT_MULTI], GT64120State), +/* CPU Address decode */ +VMSTATE_UINT32(regs[GT_SCS10LD], GT64120State), +VMSTATE_UINT32(regs[GT_SCS10HD], GT64120State), +VMSTATE_UINT32(regs[GT_SCS32LD], GT64120State), +VMSTATE_UINT32(regs[GT_SCS32HD], GT64120State), +VMSTATE_UINT32(regs[GT_CS20LD], GT64120State), +VMSTATE_UINT32(regs[GT_CS20HD], GT64120State), +VMSTATE_UINT32(regs[GT_CS3BOOTLD], GT64120State), +VMSTATE_UINT32(regs[GT_CS3BOOTHD], GT64120State), +VMSTATE_UINT32(regs[GT_PCI0IOLD], GT64120State), +VMSTATE_UINT32(regs[GT_PCI0IOHD], GT64120State), +VMSTATE_UINT32(regs[GT_PCI0M0LD], GT64120State), +VMSTATE_UINT32(regs[GT_PCI0M0HD], GT64120State), +VMSTATE_UINT32(regs[GT_ISD], GT64120State), +VMSTATE_UINT32(regs[GT_PCI0M1LD], GT64120State), +VMSTATE_UINT32(regs[GT_PCI0M1HD], GT64120State), +VMSTATE_UINT32(regs[GT_PCI1IOLD], GT64120State), +VMSTATE_UINT32(regs[GT_PCI1IOHD], GT64120State), +VMSTATE_UINT32(regs[GT_PCI1M0LD], GT64120State), +VMSTATE_UINT32(regs[GT_PCI1M0HD], GT64120State), +VMSTATE_UINT32(regs[GT_PCI1M1LD], GT64120State), +VMSTATE_UINT32(regs[GT_PCI1M1HD], GT64120State), +VMSTATE_UINT32(regs[GT_SCS10AR], GT64120State), +VMSTATE_UINT32(regs[GT_SCS32AR], GT64120State), +VMSTATE_UINT32(regs[GT_CS20R], GT64120State), +VMSTATE_UINT32(regs[GT_CS3BOOTR], GT64120State), +VMSTATE_UINT32(regs[GT_PCI0IOREMAP], GT64120State), +VMSTATE_UINT32(regs[GT_PCI0M0REMAP], GT64120State), +VMSTATE_UINT32(regs[GT_PCI0M1REMAP], GT64120State), +VMSTATE_UINT32(regs[GT_PCI1IOREMAP], GT64120State), +VMSTATE_UINT32(regs[GT_PCI1M0REMAP], GT64120State), +VMSTATE_UINT32(regs[GT_PCI1M1REMAP], GT64120State), +/* CPU Error Report */ +VMSTATE_UINT32(regs[GT_CPUERR_ADDRLO], GT64120State), +VMSTATE_UINT32(regs[GT_CPUERR_ADDRHI], GT64120State), +VMSTATE_UINT32(regs[GT_CPUERR_DATALO], GT64120State), +VMSTATE_UINT32(regs[GT_CPUERR_DATAHI], GT64120State), +VMSTATE_UINT32(regs[GT_CPUERR_PARITY], GT64120State), +/* CPU Sync Barrier */ +VMSTATE_UINT32(regs[GT_PCI0SYNC], GT64120State), +VMSTATE_UINT32(regs[GT_PCI1SYNC], GT64120State), +/* SDRAM and Device Address Decode */ +VMSTATE_UINT32(regs[GT_SCS0LD], GT64120State), +VMSTATE_UINT32(regs[GT_SCS0HD], GT64120State), +VMSTATE_UINT32(regs[GT_SCS1LD], GT64120State), +VMSTATE_UINT32(regs[GT_SCS1HD], GT64120State), +VMSTATE_UINT32(regs[GT_SCS2LD], GT64120State), +VMSTATE_UINT32(regs[GT_SCS2HD], GT64120State), +VMSTATE_UINT32(regs[GT_SCS3LD], GT64120State), +VMSTATE_UINT32(regs[GT_SCS3HD], GT64120State), +VMSTATE_UINT32(regs[GT_CS0LD], GT64120State), +VMSTATE_UINT32(regs[GT_CS0HD], GT64120State), +VMSTATE_UINT32(regs[GT_CS1LD], GT64120State), +VMSTATE_UINT32(regs[GT_CS1HD], GT64120State), +VMSTATE_UINT32(regs[GT_CS2LD], GT64120State), +VMSTATE_UINT32(regs[GT_CS2HD], GT64120State), +VMSTATE_UINT32(regs[GT_CS3LD], GT64120State), +VMSTATE_UINT32(regs[GT_CS3HD], GT64120State), +VMSTATE_UINT32(regs[GT_BOOTLD], GT64120State), +VMSTATE_UINT32(regs[GT_BOOTHD], GT64120State), +VMSTATE_UINT32(regs[GT_ADERR], GT64120State), +/* SDRAM Configuration */ +VMSTATE_UINT32(regs[GT_SDRAM_CFG], GT64120State), +VMSTATE_UINT32(
Re: [Qemu-devel] [PATCH v2] hw/mips: gt64xxx_pci: Add VMStateDescription
On 19/06/14 16:25, Aurelien Jarno wrote: > On Wed, Jun 18, 2014 at 12:10:02AM +0100, James Hogan wrote: >> From: Sanjay Lal >> >> Add VMStateDescription for GT64120 PCI emulation used by the Malta >> platform, to allow it to work with savevm/loadvm and live migration. >> >> Signed-off-by: Sanjay Lal >> [james.ho...@imgtec.com: Convert to VMState] >> Signed-off-by: James Hogan >> Cc: Aurelien Jarno >> --- >> This is based on "[Patch 03/12] KVM/MIPS: Add save/restore state APIs >> for saving/restoring KVM guests."[1]. >> >> Changes in v2: >> - Expand commit message >> - Convert to VMState (Peter Maydell) >> >> [1] https://lists.gnu.org/archive/html/qemu-devel/2013-03/msg00195.html >> --- >> hw/mips/gt64xxx_pci.c | 152 >> ++ >> 1 file changed, 152 insertions(+) >> >> diff --git a/hw/mips/gt64xxx_pci.c b/hw/mips/gt64xxx_pci.c >> index 6398514c99d2..76690ecd6ca4 100644 >> --- a/hw/mips/gt64xxx_pci.c >> +++ b/hw/mips/gt64xxx_pci.c >> @@ -312,6 +312,156 @@ static void gt64120_pci_mapping(GT64120State *s) >> } >> } >> >> +static int gt64120_post_load(void *opaque, int version_id) >> +{ >> +GT64120State *s = opaque; >> + >> +gt64120_isd_mapping(s); >> +gt64120_pci_mapping(s); >> + >> +return 0; >> +} >> + >> +static const VMStateDescription vmstate_gt64120 = { >> +.name = "gt64120", >> +.version_id = 1, >> +.minimum_version_id = 1, >> +.post_load = gt64120_post_load, >> +.fields = (VMStateField[]) { >> +/* CPU Configuration */ >> +VMSTATE_UINT32(regs[GT_CPU], GT64120State), >> +VMSTATE_UINT32(regs[GT_MULTI], GT64120State), >> +/* CPU Address decode */ >> +VMSTATE_UINT32(regs[GT_SCS10LD], GT64120State), >> +VMSTATE_UINT32(regs[GT_SCS10HD], GT64120State), >> +VMSTATE_UINT32(regs[GT_SCS32LD], GT64120State), >> +VMSTATE_UINT32(regs[GT_SCS32HD], GT64120State), >> +VMSTATE_UINT32(regs[GT_CS20LD], GT64120State), >> +VMSTATE_UINT32(regs[GT_CS20HD], GT64120State), >> +VMSTATE_UINT32(regs[GT_CS3BOOTLD], GT64120State), >> +VMSTATE_UINT32(regs[GT_CS3BOOTHD], GT64120State), >> +VMSTATE_UINT32(regs[GT_PCI0IOLD], GT64120State), >> +VMSTATE_UINT32(regs[GT_PCI0IOHD], GT64120State), >> +VMSTATE_UINT32(regs[GT_PCI0M0LD], GT64120State), >> +VMSTATE_UINT32(regs[GT_PCI0M0HD], GT64120State), >> +VMSTATE_UINT32(regs[GT_ISD], GT64120State), >> +VMSTATE_UINT32(regs[GT_PCI0M1LD], GT64120State), >> +VMSTATE_UINT32(regs[GT_PCI0M1HD], GT64120State), >> +VMSTATE_UINT32(regs[GT_PCI1IOLD], GT64120State), >> +VMSTATE_UINT32(regs[GT_PCI1IOHD], GT64120State), >> +VMSTATE_UINT32(regs[GT_PCI1M0LD], GT64120State), >> +VMSTATE_UINT32(regs[GT_PCI1M0HD], GT64120State), >> +VMSTATE_UINT32(regs[GT_PCI1M1LD], GT64120State), >> +VMSTATE_UINT32(regs[GT_PCI1M1HD], GT64120State), >> +VMSTATE_UINT32(regs[GT_SCS10AR], GT64120State), >> +VMSTATE_UINT32(regs[GT_SCS32AR], GT64120State), >> +VMSTATE_UINT32(regs[GT_CS20R], GT64120State), >> +VMSTATE_UINT32(regs[GT_CS3BOOTR], GT64120State), >> +VMSTATE_UINT32(regs[GT_PCI0IOREMAP], GT64120State), >> +VMSTATE_UINT32(regs[GT_PCI0M0REMAP], GT64120State), >> +VMSTATE_UINT32(regs[GT_PCI0M1REMAP], GT64120State), >> +VMSTATE_UINT32(regs[GT_PCI1IOREMAP], GT64120State), >> +VMSTATE_UINT32(regs[GT_PCI1M0REMAP], GT64120State), >> +VMSTATE_UINT32(regs[GT_PCI1M1REMAP], GT64120State), >> +/* CPU Error Report */ >> +VMSTATE_UINT32(regs[GT_CPUERR_ADDRLO], GT64120State), >> +VMSTATE_UINT32(regs[GT_CPUERR_ADDRHI], GT64120State), >> +VMSTATE_UINT32(regs[GT_CPUERR_DATALO], GT64120State), >> +VMSTATE_UINT32(regs[GT_CPUERR_DATAHI], GT64120State), >> +VMSTATE_UINT32(regs[GT_CPUERR_PARITY], GT64120State), >> +/* CPU Sync Barrier */ >> +VMSTATE_UINT32(regs[GT_PCI0SYNC], GT64120State), >> +VMSTATE_UINT32(regs[GT_PCI1SYNC], GT64120State), >> +/* SDRAM and Device Address Decode */ >> +VMSTATE_UINT32(regs[GT_SCS0LD], GT64120State), >> +VMSTATE_UINT32(regs[GT_SCS0HD], GT64120State), >> +VMSTATE_UINT32(regs[GT_SCS1LD], GT64120State), >> +VMSTATE_UINT32(regs[GT_SCS1HD
Re: [Qemu-devel] [PATCH v5 10/12] hw/mips: malta: Add KVM support
Hi, On 20/06/14 07:07, Paolo Bonzini wrote: > - Messaggio originale - >> Da: "Aurelien Jarno" >> A: "Sanjay Lal" >> Cc: "James Hogan" , qemu-devel@nongnu.org, "Peter >> Maydell" , >> k...@vger.kernel.org, "Gleb Natapov" , "Paolo Bonzini" >> >> Inviato: Giovedì, 19 giugno 2014 23:47:34 >> Oggetto: Re: [Qemu-devel] [PATCH v5 10/12] hw/mips: malta: Add KVM support >> >> On Thu, Jun 19, 2014 at 12:34:24PM -0700, Sanjay Lal wrote: >>> >>> On Jun 19, 2014, at 9:27 AM, Aurelien Jarno wrote: >>> >>>> On Tue, Jun 17, 2014 at 11:10:35PM +0100, James Hogan wrote: >>>>> In KVM mode the bootrom is loaded and executed from the last 1MB of >>>>> DRAM. >>>> >>>> What is the reason for that? I am not opposed to that, but if it is >>>> really needed, it means that loading a bootloader into the flash area >>>> (for example YAMON) won't work and that this should be forbidden to the >>>> user. >>>> >>> >>> In trap and emulate mode, both the kernel and userland run in user mode on >>> the processor. Virtual addresses >= 0x8000 are only accessible in >>> kernel mode, and the default flash area (VA: 0xbfc0/PA: 0x1fc0) >>> falls in this range. >>> >>> We therefore decided to relocate the bootloader to the last 1MB of RAM. >>> This area is excluded from the RAM ranges supplied to the kernel, so it >>> should not be accessible to the user. I did recently try relocating the bootloader to the reset address in the T&E KSeg0 (i.e. PA=0x1fc0, VA=0x5fc0), but the current MIPS KVM implementation in the kernel has some limitations when it comes to memory regions. It allocates a linear guest_pmap array (for GPA->RPA page mapping) based only on the first memory region committed, so if you set e.g. mem=64MB then physical memory according to guest_pmap won't reach the reset address and it fails to map it. The kernel needs fixing to use a more flexible physical page table structure first really. >> Thanks for the explanation. It means we should disable the support for >> booting from the flash (using -pflash) in KVM mode, as it would simply >> not work. > > My idea was to add a machines-specific option umkernel=on, and require it > in order to run KVM. Later we can add umkernel=on support for TCG as well, FYI I tried this and it was a fairly small change (fixing CP0_EBase initialisation and switching a couple of kvm_enabled() checks to something like mips_um_ksegs_enabled()). Needs more testing though. > while umkernel=off with KVM requires virtualization extensions. > > The same option can disable pflash boot. > > What do you think? I think with an executable flash region / reset address the pflash option could be made to work, but of course you'd probably need a relocated flash image too, which may make the option less useful (and it presumably isn't like a kernel ELF where you can detect what address it's linked). For now disabling Malta non kernel loads in KVM mode makes sense I think. Thanks James
Re: [Qemu-devel] [PATCH v5 10/12] hw/mips: malta: Add KVM support
On 19/06/14 22:47, Aurelien Jarno wrote: > On Thu, Jun 19, 2014 at 12:34:24PM -0700, Sanjay Lal wrote: >> >> On Jun 19, 2014, at 9:27 AM, Aurelien Jarno wrote: >> >>> On Tue, Jun 17, 2014 at 11:10:35PM +0100, James Hogan wrote: >>>> In KVM mode the bootrom is loaded and executed from the last 1MB of >>>> DRAM. >>> >>> What is the reason for that? I am not opposed to that, but if it is >>> really needed, it means that loading a bootloader into the flash area >>> (for example YAMON) won't work and that this should be forbidden to the >>> user. >>> >> >> In trap and emulate mode, both the kernel and userland run in user mode on >> the processor. Virtual addresses >= 0x8000 are only accessible in kernel >> mode, and the default flash area (VA: 0xbfc0/PA: 0x1fc0) falls in >> this range. >> >> We therefore decided to relocate the bootloader to the last 1MB of RAM. >> This area is excluded from the RAM ranges supplied to the kernel, so it >> should not be accessible to the user. >> > > Thanks for the explanation. It means we should disable the support for > booting from the flash (using -pflash) in KVM mode, as it would simply > not work. > Hi Aurelien, Is this fixup to the malta patch the sort of thing you had in mind? If so I'll generate a v6 patchset with it. Cheers James diff --git a/hw/mips/mips_malta.c b/hw/mips/mips_malta.c index 8bc5392b4223..91b0ce566111 100644 --- a/hw/mips/mips_malta.c +++ b/hw/mips/mips_malta.c @@ -1052,6 +1052,12 @@ void mips_malta_init(MachineState *machine) bootloader_run_addr, kernel_entry); } } else { +/* The flash region isn't executable from a KVM T&E guest */ +if (kvm_enabled()) { +error_report("KVM enabled but no -kernel argument was specified. " + "Booting from flash is not supported with KVM T&E."); +exit(1); +} /* Load firmware from flash. */ if (!dinfo) { /* Load a BIOS image. */
[Qemu-devel] [PATCH v3] hw/mips: gt64xxx_pci: Add VMStateDescription
From: Sanjay Lal Add VMStateDescription for GT64120 PCI emulation used by the Malta platform, to allow it to work with savevm/loadvm and live migration. The entire register array is saved/restored using VMSTATE_UINT32_ARRAY (fixed length GT_REGS = 1024). Signed-off-by: Sanjay Lal [james.ho...@imgtec.com: Convert to VMState] Signed-off-by: James Hogan Cc: Aurelien Jarno --- This is based on "[Patch 03/12] KVM/MIPS: Add save/restore state APIs for saving/restoring KVM guests."[1]. Changes in v3: - Save entire register array using VMSTATE_UINT32_ARRAY (which is fixed length of GT_REGS = 1024) rather than individual registers. This is safer in case an important register is missed or new emulated functionality is added. (Aurelien Jarno) Changes in v2: - Expand commit message - Convert to VMState (Peter Maydell) [1] https://lists.gnu.org/archive/html/qemu-devel/2013-03/msg00195.html --- hw/mips/gt64xxx_pci.c | 23 +++ 1 file changed, 23 insertions(+) diff --git a/hw/mips/gt64xxx_pci.c b/hw/mips/gt64xxx_pci.c index 6398514c99d2..22f63ce0c8af 100644 --- a/hw/mips/gt64xxx_pci.c +++ b/hw/mips/gt64xxx_pci.c @@ -312,6 +312,27 @@ static void gt64120_pci_mapping(GT64120State *s) } } +static int gt64120_post_load(void *opaque, int version_id) +{ +GT64120State *s = opaque; + +gt64120_isd_mapping(s); +gt64120_pci_mapping(s); + +return 0; +} + +static const VMStateDescription vmstate_gt64120 = { +.name = "gt64120", +.version_id = 1, +.minimum_version_id = 1, +.post_load = gt64120_post_load, +.fields = (VMStateField[]) { +VMSTATE_UINT32_ARRAY(regs, GT64120State, GT_REGS), +VMSTATE_END_OF_LIST() +} +}; + static void gt64120_writel (void *opaque, hwaddr addr, uint64_t val, unsigned size) { @@ -1174,9 +1195,11 @@ static const TypeInfo gt64120_pci_info = { static void gt64120_class_init(ObjectClass *klass, void *data) { +DeviceClass *dc = DEVICE_CLASS(klass); SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass); sdc->init = gt64120_init; +dc->vmsd = &vmstate_gt64120; } static const TypeInfo gt64120_info = { -- 1.9.3
Re: [Qemu-devel] [PATCH v3] hw/mips: gt64xxx_pci: Add VMStateDescription
On 20/06/14 11:25, James Hogan wrote: > From: Sanjay Lal > > Add VMStateDescription for GT64120 PCI emulation used by the Malta > platform, to allow it to work with savevm/loadvm and live migration. > > The entire register array is saved/restored using VMSTATE_UINT32_ARRAY > (fixed length GT_REGS = 1024). > > Signed-off-by: Sanjay Lal > [james.ho...@imgtec.com: Convert to VMState] > Signed-off-by: James Hogan > Cc: Aurelien Jarno > --- > This is based on "[Patch 03/12] KVM/MIPS: Add save/restore state APIs > for saving/restoring KVM guests."[1]. > > Changes in v3: > - Save entire register array using VMSTATE_UINT32_ARRAY (which is fixed >length of GT_REGS = 1024) rather than individual registers. This is >safer in case an important register is missed or new emulated >functionality is added. (Aurelien Jarno) For the record, Aurelien's question about saving all registers or only specific ones is still open (I also don't have enough experience to be sure, although I prefer the approach in v3). On 19/06/14 16:51, Aurelien Jarno wrote: > That said there might be some drawbacks in doing that, and I don't > really have enough experience to judge about that. It would be nice if > some more people can give their opinion there. Note, new emulated functionality may still require VMState versioning to handle unexpected zero register values in restored state. Cheers James
Re: [Qemu-devel] [PATCH v5 10/12] hw/mips: malta: Add KVM support
On 20/06/14 12:19, Aurelien Jarno wrote: > On Fri, Jun 20, 2014 at 12:38:30PM +0200, Paolo Bonzini wrote: >> Il 20/06/2014 11:10, Aurelien Jarno ha scritto: My idea was to add a machines-specific option umkernel=on, and require it in order to run KVM. Later we can add umkernel=on support for TCG as well, while umkernel=off with KVM requires virtualization extensions. The same option can disable pflash boot. What do you think? >>> >>> For what I understand the current KVM support in MIPS uses trap and >>> emulate and thus doesn't need hardware support, just a recent kernel >>> with the option enabled. >> >> Yes, but work to support virtualization extensions is underway. >> Patches were posted a few months ago. >> >>> That's why I do wonder if there is a real point >>> in supporting UM kernels in TCG mode. >> >> Debugging, mainly. It is sometimes useful to compare TCG with KVM >> on x86, and I suppose it could be the same on MIPS. > > Ok, then we can indeed add a umkernel option, which is always enabled > with KVM, and which disable the flash (and why not other devices) in > that case. > > At some point it might be a good idea to add a specific machine for > emulation/virtualization, like it is done on ARM, which do not have to > handle this kind of devices, and which does not have all the current > limitations of the Malta board. FYI Cavium have been working on a para-virtualised machine which they use with their VZ KVM implementation. They're using lkvm, but I expect it will make sense to port that to QEMU too. lkvm patchset (applied): https://www.mail-archive.com/kvm%40vger.kernel.org/msg102792.html linux kernel patchset (merged in v3.16-rc1): https://www.mail-archive.com/kvm%40vger.kernel.org/msg102806.html Cheers James
qemu-devel@nongnu.org
In KVM trap & emulate (T&E) mode the flash reset region at 0xbfc0 isn't executable, which is why the minimal kernel bootloader is loaded and executed from the last 1MB of DRAM instead. Therefore if no kernel is provided on the command line and KVM is enabled, exit with an error since booting from flash will fail. Reported-by: Aurelien Jarno Signed-off-by: James Hogan Cc: Paolo Bonzini --- hw/mips/mips_malta.c | 6 ++ 1 file changed, 6 insertions(+) diff --git a/hw/mips/mips_malta.c b/hw/mips/mips_malta.c index 8bc5392b4223..91b0ce566111 100644 --- a/hw/mips/mips_malta.c +++ b/hw/mips/mips_malta.c @@ -1052,6 +1052,12 @@ void mips_malta_init(MachineState *machine) bootloader_run_addr, kernel_entry); } } else { +/* The flash region isn't executable from a KVM T&E guest */ +if (kvm_enabled()) { +error_report("KVM enabled but no -kernel argument was specified. " + "Booting from flash is not supported with KVM T&E."); +exit(1); +} /* Load firmware from flash. */ if (!dinfo) { /* Load a BIOS image. */ -- 1.9.3
qemu-devel@nongnu.org
On 20/06/14 14:17, Andreas Färber wrote: > Hi, > > Am 20.06.2014 13:47, schrieb James Hogan: >> In KVM trap & emulate (T&E) mode the flash reset region at 0xbfc0 >> isn't executable, which is why the minimal kernel bootloader is loaded >> and executed from the last 1MB of DRAM instead. >> >> Therefore if no kernel is provided on the command line and KVM is >> enabled, exit with an error since booting from flash will fail. >> >> Reported-by: Aurelien Jarno >> Signed-off-by: James Hogan >> Cc: Paolo Bonzini >> --- >> hw/mips/mips_malta.c | 6 ++ >> 1 file changed, 6 insertions(+) > > Previous commits have used just "mips_malta:", so suggest to do the same > for consistency - or clean hw/mips/ dir up by renaming the file to just > malta.c and use "mips/malta:". > > http://git.qemu-project.org/?p=qemu.git;a=history;f=hw/mips/mips_malta.c;h=f4a7d47129526f6762eccc47251c8cf3cd27f928;hb=HEAD Noted > > That said, > >> diff --git a/hw/mips/mips_malta.c b/hw/mips/mips_malta.c >> index 8bc5392b4223..91b0ce566111 100644 >> --- a/hw/mips/mips_malta.c >> +++ b/hw/mips/mips_malta.c >> @@ -1052,6 +1052,12 @@ void mips_malta_init(MachineState *machine) >> bootloader_run_addr, kernel_entry); >> } >> } else { >> +/* The flash region isn't executable from a KVM T&E guest */ >> +if (kvm_enabled()) { >> +error_report("KVM enabled but no -kernel argument was >> specified. " >> + "Booting from flash is not supported with KVM >> T&E."); >> +exit(1); >> +} >> /* Load firmware from flash. */ >> if (!dinfo) { >> /* Load a BIOS image. */ > > Reviewed-by: Andreas Färber > > Are users expected to know/understand "KVM T&E"? You don't test for that > T&E mode here, so you could either shorten the message to just "KVM" or > replace the check with a more specific one. Yeh, not mentioning T&E at all would be better actually. The limitation is technically a MIPS KVM one rather than being T&E specific. I'll post a v2. Thanks for reviewing James > Since qtest does not use KVM on MIPS today, exiting without -kernel > should be fine, but may need updating if we ever get to that. > > Regards, > Andreas >
[Qemu-devel] [PATCH v2] mips_malta: Don't boot from flash with KVM
In KVM mode the flash reset region at 0xbfc0 isn't executable, which is why the minimal kernel bootloader is loaded and executed from the last 1MB of DRAM instead. Therefore if no kernel is provided on the command line and KVM is enabled, exit with an error since booting from flash will fail. Reported-by: Aurelien Jarno Signed-off-by: James Hogan Reviewed-by: Andreas Färber Cc: Paolo Bonzini --- Changes in v2: - Remove mention of T&E. There is currently no distinction since VZ isn't supported, and technically the limitation isn't T&E specific. (Andreas Färber) --- hw/mips/mips_malta.c | 6 ++ 1 file changed, 6 insertions(+) diff --git a/hw/mips/mips_malta.c b/hw/mips/mips_malta.c index 8bc5392b4223..a54ed65a6b73 100644 --- a/hw/mips/mips_malta.c +++ b/hw/mips/mips_malta.c @@ -1052,6 +1052,12 @@ void mips_malta_init(MachineState *machine) bootloader_run_addr, kernel_entry); } } else { +/* The flash region isn't executable from a KVM guest */ +if (kvm_enabled()) { +error_report("KVM enabled but no -kernel argument was specified. " + "Booting from flash is not supported with KVM."); +exit(1); +} /* Load firmware from flash. */ if (!dinfo) { /* Load a BIOS image. */ -- 1.9.3
[Qemu-devel] [PATCH v4] gt64xxx_pci: Add VMStateDescription
From: Sanjay Lal Add VMStateDescription for GT64120 PCI emulation used by the Malta platform, to allow it to work with savevm/loadvm and live migration. The entire register array is saved/restored using VMSTATE_UINT32_ARRAY (fixed length GT_REGS = 1024). Signed-off-by: Sanjay Lal [james.ho...@imgtec.com: Convert to VMState] Signed-off-by: James Hogan Cc: Aurelien Jarno Cc: Andreas Färber --- This is based on "[Patch 03/12] KVM/MIPS: Add save/restore state APIs for saving/restoring KVM guests."[1]. Changes in v4: - Drop redundant "hw/mips:" prefix from subject line. (Andreas Färber) Changes in v3: - Save entire register array using VMSTATE_UINT32_ARRAY (which is fixed length of GT_REGS = 1024) rather than individual registers. This is safer in case an important register is missed or new emulated functionality is added. (Aurelien Jarno) Changes in v2: - Expand commit message - Convert to VMState (Peter Maydell) [1] https://lists.gnu.org/archive/html/qemu-devel/2013-03/msg00195.html --- hw/mips/gt64xxx_pci.c | 23 +++ 1 file changed, 23 insertions(+) diff --git a/hw/mips/gt64xxx_pci.c b/hw/mips/gt64xxx_pci.c index 6398514c99d2..22f63ce0c8af 100644 --- a/hw/mips/gt64xxx_pci.c +++ b/hw/mips/gt64xxx_pci.c @@ -312,6 +312,27 @@ static void gt64120_pci_mapping(GT64120State *s) } } +static int gt64120_post_load(void *opaque, int version_id) +{ +GT64120State *s = opaque; + +gt64120_isd_mapping(s); +gt64120_pci_mapping(s); + +return 0; +} + +static const VMStateDescription vmstate_gt64120 = { +.name = "gt64120", +.version_id = 1, +.minimum_version_id = 1, +.post_load = gt64120_post_load, +.fields = (VMStateField[]) { +VMSTATE_UINT32_ARRAY(regs, GT64120State, GT_REGS), +VMSTATE_END_OF_LIST() +} +}; + static void gt64120_writel (void *opaque, hwaddr addr, uint64_t val, unsigned size) { @@ -1174,9 +1195,11 @@ static const TypeInfo gt64120_pci_info = { static void gt64120_class_init(ObjectClass *klass, void *data) { +DeviceClass *dc = DEVICE_CLASS(klass); SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass); sdc->init = gt64120_init; +dc->vmsd = &vmstate_gt64120; } static const TypeInfo gt64120_info = { -- 1.9.3
[Qemu-devel] [PATCH] qemu-char: fix infinite recursion connecting to monitor pty
Since commit bd5c51e (qemu-char: don't issue CHR_EVENT_OPEN in a BH), an infinite recursion occurs when putting the monitor on a pty (-monitor pty) and connecting a terminal to the slave port. This is because of the qemu_chr_be_event(s, CHR_EVENT_OPENED) added to qemu_chr_be_generic_open(). This event is captured by monitor_event() which prints a welcome message to the character device. The flush of that welcome message retriggers another open event in pty_chr_state() because it checks s->connected, but only sets it to 1 after calling qemu_chr_be_generic_open(). I've fixed this by setting s->connected = 1 before the call to qemu_chr_be_generic_open() instead of after, so that the recursive pty_chr_state() doesn't call it again. An example snippet of repeating backtrace: ... #107486 0x007aec58 in monitor_flush (mon=0xf418b0) at qemu/monitor.c:288 #107487 0x007aee7c in monitor_puts (mon=0xf418b0, str=0x1176d07 "") at qemu/monitor.c:322 #107488 0x007aef20 in monitor_vprintf (mon=0xf418b0, fmt=0x8d4820 "QEMU %s monitor - type 'help' for more information\n", ap=0x7f432be0) at qemu/monitor.c:339 #107489 0x007aefac in monitor_printf (mon=0xf418b0, fmt=0x8d4820 "QEMU %s monitor - type 'help' for more information\n") at qemu/monitor.c:347 #107490 0x007ba4bc in monitor_event (opaque=0xf418b0, event=2) at qemu/monitor.c:4699 #107491 0x00684c28 in qemu_chr_be_event (s=0xf37788, event=2) at qemu/qemu-char.c:108 #107492 0x00684c70 in qemu_chr_be_generic_open (s=0xf37788) at qemu/qemu-char.c:113 #107493 0x006880a4 in pty_chr_state (chr=0xf37788, connected=1) at qemu/qemu-char.c:1145 #107494 0x00687fa4 in pty_chr_update_read_handler (chr=0xf37788) at qemu/qemu-char.c:1121 #107495 0x00687c9c in pty_chr_write (chr=0xf37788, buf=0x70b3c008 , len=538720) at qemu/qemu-char.c:1063 #107496 0x00684cc4 in qemu_chr_fe_write (s=0xf37788, buf=0x70b3c008 , len=538720) at qemu/qemu-char.c:118 ... Signed-off-by: James Hogan Cc: Michael Roth Cc: Anthony Liguori --- Note the commit I mentioned Cc's gnu-sta...@nongnu.org. Assuming this patch is acceptable it probably makes sense for it to follow the other patch into stable too. qemu-char.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qemu-char.c b/qemu-char.c index 16f3ad7..1be1cf6 100644 --- a/qemu-char.c +++ b/qemu-char.c @@ -1142,8 +1142,8 @@ static void pty_chr_state(CharDriverState *chr, int connected) s->timer_tag = 0; } if (!s->connected) { -qemu_chr_be_generic_open(chr); s->connected = 1; +qemu_chr_be_generic_open(chr); s->fd_tag = io_add_watch_poll(s->fd, pty_chr_read_poll, pty_chr_read, chr); } } -- 1.8.1.2
[Qemu-devel] [PATCH] tcg/mips: fix invalid op definition errors
tcg/mips/tcg-target.h defines various operations conditionally depending upon the isa revision, however these operations are included in mips_op_defs[] unconditionally resulting in the following runtime errors if CONFIG_DEBUG_TCG is defined: Invalid op definition for movcond_i32 Invalid op definition for rotl_i32 Invalid op definition for rotr_i32 Invalid op definition for deposit_i32 Invalid op definition for bswap16_i32 Invalid op definition for bswap32_i32 tcg/tcg.c:1196: tcg fatal error Fix with ifdefs like the i386 backend does for movcond_i32. Signed-off-by: James Hogan Cc: Aurelien Jarno Cc: Richard Henderson --- tcg/mips/tcg-target.c | 10 ++ 1 file changed, 10 insertions(+) diff --git a/tcg/mips/tcg-target.c b/tcg/mips/tcg-target.c index 373c364..793532e 100644 --- a/tcg/mips/tcg-target.c +++ b/tcg/mips/tcg-target.c @@ -1617,19 +1617,29 @@ static const TCGTargetOpDef mips_op_defs[] = { { INDEX_op_shl_i32, { "r", "rZ", "ri" } }, { INDEX_op_shr_i32, { "r", "rZ", "ri" } }, { INDEX_op_sar_i32, { "r", "rZ", "ri" } }, +#if TCG_TARGET_HAS_rot_i32 { INDEX_op_rotr_i32, { "r", "rZ", "ri" } }, { INDEX_op_rotl_i32, { "r", "rZ", "ri" } }, +#endif +#if TCG_TARGET_HAS_bswap16_i32 { INDEX_op_bswap16_i32, { "r", "r" } }, +#endif +#if TCG_TARGET_HAS_bswap32_i32 { INDEX_op_bswap32_i32, { "r", "r" } }, +#endif { INDEX_op_ext8s_i32, { "r", "rZ" } }, { INDEX_op_ext16s_i32, { "r", "rZ" } }, +#if TCG_TARGET_HAS_deposit_i32 { INDEX_op_deposit_i32, { "r", "0", "rZ" } }, +#endif { INDEX_op_brcond_i32, { "rZ", "rZ" } }, +#if TCG_TARGET_HAS_movcond_i32 { INDEX_op_movcond_i32, { "r", "rZ", "rZ", "rZ", "0" } }, +#endif { INDEX_op_setcond_i32, { "r", "rZ", "rZ" } }, { INDEX_op_setcond2_i32, { "r", "rZ", "rZ", "rZ", "rZ" } }, -- 1.8.1.2
Re: [Qemu-devel] [PATCH] tcg/mips: fix invalid op definition errors
On 08/08/13 17:10, Richard Henderson wrote: > On 08/08/2013 04:40 AM, James Hogan wrote: >> tcg/mips/tcg-target.h defines various operations conditionally depending >> upon the isa revision, however these operations are included in >> mips_op_defs[] unconditionally resulting in the following runtime errors >> if CONFIG_DEBUG_TCG is defined: >> >> Invalid op definition for movcond_i32 >> Invalid op definition for rotl_i32 >> Invalid op definition for rotr_i32 >> Invalid op definition for deposit_i32 >> Invalid op definition for bswap16_i32 >> Invalid op definition for bswap32_i32 >> tcg/tcg.c:1196: tcg fatal error >> >> Fix with ifdefs like the i386 backend does for movcond_i32. >> >> Signed-off-by: James Hogan >> Cc: Aurelien Jarno >> Cc: Richard Henderson > > Reviewed-by: Richard Henderson Thanks, > Perfect for 1.6. > > For 1.7 it would be really nice if you could figure out some way to make > these runtime tests, instead of ifdefs. I'd have said getauxval(3), but > the mips kernel doesn't seem to define any identifying bits. Perhaps > that's the first thing that ought to get fixed... Yes, the auxvec sounds ideal for this, and AT_HWCAP is already used for cpuid on x86. There were some patches a while ago for exposing the C0 configX registers through sysfs, but auxvec sounds cleaner IMO. Cheers James
Re: [Qemu-devel] [PATCH for-1.6] mips_malta: do not raise exceptions when accessing invalid memory
On 12 August 2013 20:44, Aurelien Jarno wrote: > Since commit c658b94f6e8c206c59d02aa6fbac285b86b53d2c, MIPS raises > exceptions when accessing invalid memory. This is not the correct > behaviour for MIPS Malta Core LV, as the GT-64120A system controller > just ignore undecoded access. This feature is used by the Linux kernel > to probe for some devices. > > Emulate the correct behaviour in QEMU by adding an empty slot covering > the entire memory space decoded by the GT-64120A. > > Signed-off-by: Aurelien Jarno > --- > @@ -908,6 +909,11 @@ void mips_malta_init(QEMUMachineInitArgs *args) > DeviceState *dev = qdev_create(NULL, TYPE_MIPS_MALTA); > MaltaState *s = MIPS_MALTA(dev); > > +/* The whole address space decoded by the GT-64120A doesn't generate > + exception when accessing invalid memory. Create an empty slot to > + emulate this feature. */ > +empty_slot_init(0, 0x1fff); Out of interest, any particular reason not to put this in hw/mips/gt64xxx_pci.c? As far as I can tell from your description it's specific to the GT-64* system controller rather than the malta board? Cheers James
[Qemu-devel] [PATCH 1/1] mc146818rtc: correct UIP hold length
The UIP (update in progress) hold time was set to 8 32.768KHz clock cycles (around 244uS). However the timing diagram in the datasheet (Figure 16) shows that the UIP bit is held for both the update cycle time (either 248uS or 1984uS depending on the clock source), and the minimum time before update cycle (244uS). It's clear from periodic_timer_update() that only a 32.768KHz clock source is expected, so correct the hold time to 244uS + 1984uS = 73 32.768KHz clock cycles. Signed-off-by: James Hogan Cc: Andreas Färber Cc: Anthony Liguori Cc: Igor Mammedov Cc: Paolo Bonzini Cc: Yang Zhang --- hw/timer/mc146818rtc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hw/timer/mc146818rtc.c b/hw/timer/mc146818rtc.c index 3c3baac..6000feb 100644 --- a/hw/timer/mc146818rtc.c +++ b/hw/timer/mc146818rtc.c @@ -55,7 +55,7 @@ #define RTC_REINJECT_ON_ACK_COUNT 20 #define RTC_CLOCK_RATE32768 -#define UIP_HOLD_LENGTH (8 * NSEC_PER_SEC / 32768) +#define UIP_HOLD_LENGTH (73 * NSEC_PER_SEC / 32768) #define MC146818_RTC(obj) OBJECT_CHECK(RTCState, (obj), TYPE_MC146818_RTC) @@ -597,7 +597,7 @@ static int update_in_progress(RTCState *s) } guest_nsec = get_guest_rtc_ns(s); -/* UIP bit will be set at last 244us of every second. */ +/* UIP bit will be set at last 1984us + 244us of every second. */ if ((guest_nsec % NSEC_PER_SEC) >= (NSEC_PER_SEC - UIP_HOLD_LENGTH)) { return 1; } -- 1.8.1.2
Re: [Qemu-devel] [PATCH 2/2] target-mips: implement UserLocal Register
Hi Petar, On Friday 16 May 2014 20:13:34 Petar Jovanovic wrote: > From: Petar Jovanovic > > From MIPS documentation (Volume III): > > UserLocal Register (CP0 Register 4, Select 2) > Compliance Level: Recommended. > > The UserLocal register is a read-write register that is not interpreted by > the hardware and conditionally readable via the RDHWR instruction. > > This register only exists if the Config3-ULRI register field is set. > > Privileged software may write this register with arbitrary information and > make it accessable to unprivileged software via register 29 (ULR) of the > RDHWR instruction. To do so, bit 29 of the HWREna register must be set to a > 1 to enable unprivileged access to the register. > > Signed-off-by: Petar Jovanovic > --- > target-mips/cpu.h |2 ++ > target-mips/helper.h|1 + > target-mips/op_helper.c | 20 +++- > target-mips/translate.c | 43 +-- > 4 files changed, 63 insertions(+), 3 deletions(-) I think you need to add it to cpu_save/cpu_load in target-mips/machine.c too, otherwise snapshotting and live migration may break. Cheers James
Re: [Qemu-devel] [PATCH 2/2] target-mips: implement UserLocal Register
On Friday 16 May 2014 20:13:34 Petar Jovanovic wrote: > diff --git a/target-mips/cpu.h b/target-mips/cpu.h > index 6c2014e..bb18fb8 100644 > --- a/target-mips/cpu.h > +++ b/target-mips/cpu.h > @@ -227,6 +227,7 @@ struct CPUMIPSState { > target_ulong CP0_EntryLo0; > target_ulong CP0_EntryLo1; > target_ulong CP0_Context; > +target_ulong CP0_UserLocal; Also according to the MT ASE UserLocal is replicated for each TC, so this should really go in struct TCState I think. Cheers James
Re: [Qemu-devel] [PATCH 01/20] target-mips: add MSA defines and data structure
Hi, On 14/07/14 10:55, Yongbok Kim wrote: > +union wr_t { > +int8_t b[MSA_WRLEN/8]; > +int16_t h[MSA_WRLEN/16]; > +int32_t w[MSA_WRLEN/32]; > +int64_t d[MSA_WRLEN/64]; This is incorrect on a big endian host. The least significant bits of the lowest indexed element should always alias. With a compiler for little endian this will work fine since b[0] will alias the least significant bits of h[0], w[0], and d[0], whereas with a compiler for big endian, b[0] will alias the upper byte of h[0], w[0], and d[0]. > diff --git a/target-mips/mips-defs.h b/target-mips/mips-defs.h > index 9dfa516..11722bb 100644 > --- a/target-mips/mips-defs.h > +++ b/target-mips/mips-defs.h > @@ -41,6 +41,7 @@ > #define ASE_MT 0x0002 > #define ASE_SMARTMIPS 0x0004 > #define ASE_MICROMIPS 0x0008 > +#define ASE_MSA 0x0010 inconsistent whitespace... though maybe it was already incorrect. Cheers James
Re: [Qemu-devel] [PATCH 06/20] target-mips: add MSA opcode enum
Hi, On 14/07/14 10:55, Yongbok Kim wrote: > @@ -835,6 +839,8 @@ enum { > OPC_BC1 = (0x08 << 21) | OPC_CP1, /* bc */ > OPC_BC1ANY2 = (0x09 << 21) | OPC_CP1, > OPC_BC1ANY4 = (0x0A << 21) | OPC_CP1, > +OPC_MSA_BZ_V = (0x0B << 21) | OPC_CP1, > +OPC_MSA_BNZ_V = (0x0F << 21) | OPC_CP1, I don't think any of the existing secondary opcodes have the ASE prefixed, and the instruction mnemonics should already be unique, so is it worth dropping the MSA_ on these and the other secondary opcodes? > +/* 2R instruction df(bits 17..16) = _b, _h, _w, _d */ > +OPC_MSA_FILL_df = (0x00 << 16) | OPC_MSA_2R, > +OPC_MSA_PCNT_df = (0x04 << 16) | OPC_MSA_2R, > +OPC_MSA_NLOC_df = (0x08 << 16) | OPC_MSA_2R, > +OPC_MSA_NLZC_df = (0x0C << 16) | OPC_MSA_2R, it might be more consistent (and more directly comparable to the encoding table in the manual) to use a shift of 18 here, kind of like you did for the I5 instructions. Same for the 2RF ones below but with a shift of 17. > + > +/* 2RF instruction df(bit 16) = _w, _d */ > +OPC_MSA_FINT_S_df = (0x18 << 16) | OPC_MSA_2RF, > +OPC_MSA_FINT_U_df = (0x1A << 16) | OPC_MSA_2RF, the manual calls these two FTINT rather than FINT Otherwise Reviewed-by: James Hogan Cheers James
Re: [Qemu-devel] [PATCH 01/20] target-mips: add MSA defines and data structure
Hi, On 14/07/14 10:55, Yongbok Kim wrote: > +typedef struct CPUMIPSMSAContext CPUMIPSMSAContext; > +struct CPUMIPSMSAContext { > +int32_t msair; > +int32_t msacsr; > +int32_t msaaccess; > +int32_t msasave; > +int32_t msamodify; > +int32_t msarequest; > +int32_t msamap; > +int32_t msaunmap; > + > +float_status fp_status; > +}; > + > typedef union fpr_t fpr_t; > union fpr_t { > float64 fd; /* ieee double precision */ > float32 fs[2];/* ieee single precision */ > uint64_t d;/* binary double fixed-point */ > uint32_t w[2]; /* binary single fixed-point */ > +/* FPU/MSA register mapping is not tested on big-endian hosts. */ > +wr_t wr; /* vector data */ > }; > /* define FP_ENDIAN_IDX to access the same location > * in the fpr_t union regardless of the host endianness > @@ -175,6 +237,7 @@ typedef struct CPUMIPSState CPUMIPSState; > struct CPUMIPSState { > TCState active_tc; > CPUMIPSFPUContext active_fpu; > +CPUMIPSMSAContext active_msa; According to the manual, only the msair register is shared between thread contexts, each thread context has its own version of the rest of the msa registers, so most of this should be TCState I think. Cheers James
Re: [Qemu-devel] [PATCH 07/20] target-mips: add msa_reset(), global msa register
Hi, On 14/07/14 10:55, Yongbok Kim wrote: > +static const char * const msaregnames[] = { > +"w0.d0", "w0.d1", "w1.d0", "w1.d1", > +"w2.d0", "w2.d1", "w3.d0", "w3.d1", > +"w4.d0", "w4.d1", "w4.d0", "w4.d1", I think those last 2 should be w5.d0 and w5.d1 > +static inline int check_msa_access(CPUMIPSState *env, DisasContext *ctx, > +int wt, int ws, int wd) > +{ > +if (unlikely((ctx->hflags & MIPS_HFLAG_FPU) && > + !(ctx->hflags & MIPS_HFLAG_F64))) { > +generate_exception(ctx, EXCP_RI); > +return 0; > +} > + > +if (unlikely(!(ctx->hflags & MIPS_HFLAG_MSA))) { > +if (ctx->insn_flags & ASE_MSA) { > +generate_exception(ctx, EXCP_MSADIS); > +return 0; > +} else { > +generate_exception(ctx, EXCP_RI); > +return 0; > +} > +} > + > +if (env->active_msa.msair & MSAIR_WRP_BIT) { > +int curr_request = 0; > +if (wd != -1) { > +curr_request |= (1 << wd); > +} > +if (wt != -1) { > +curr_request |= (1 << wt); > +} > +if (ws != -1) { > +curr_request |= (1 << ws); > +} > +env->active_msa.msarequest = curr_request > +& (~env->active_msa.msaaccess | env->active_msa.msasave); > +if (unlikely(env->active_msa.msarequest != 0)) { Are you sure it's safe to access env here during code generation? How do you guarantee the values at translation time match the values at run time? > +generate_exception(ctx, EXCP_MSADIS); > +return 0; > +} > +} > +return 1; > +} newline between functions? > diff --git a/target-mips/translate_init.c b/target-mips/translate_init.c > index 29dc2ef..9e0f67b 100644 > --- a/target-mips/translate_init.c > +++ b/target-mips/translate_init.c > @@ -688,3 +688,48 @@ static void mvp_init (CPUMIPSState *env, const > mips_def_t *def) > (0x0 << CP0MVPC1_PCX) | (0x0 << CP0MVPC1_PCP2) | > (0x1 << CP0MVPC1_PCP1); > } > + > +static void msa_reset(CPUMIPSState *env) > +{ > +#ifdef CONFIG_USER_ONLY > +/* MSA access enabled */ > +env->CP0_Config5 |= 1 << CP0C5_MSAEn; > + > +/* DSP and CP1 enabled, 64-bit FPRs */ > +env->CP0_Status |= (1 << CP0St_MX); > +env->hflags |= MIPS_HFLAG_DSP; why do you enable DSP? > +env->CP0_Status |= (1 << CP0St_CU1) | (1 << CP0St_FR); > +env->hflags |= MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X; shouldn't that depend on the program being loaded, and whether it's built for fp32 or fp64? > +#endif > + > +/* Vector register partitioning not implemented */ > +env->active_msa.msair = 0; > +env->active_msa.msaaccess = 0x; the reset state is 0 according to the manual. Maybe this should depend on CONFIG_USER_ONLY. Cheers James
Re: [Qemu-devel] [PATCH 08/20] target-mips: add msa_helper.c
On 14/07/14 10:55, Yongbok Kim wrote: > +#define B(pwr, i) (((wr_t *)pwr)->b[i]) > +#define BR(pwr, i) (((wr_t *)pwr)->b[i]) > +#define BL(pwr, i) (((wr_t *)pwr)->b[i + MSA_WRLEN/16]) macro argument references should be enclosed in brackets really (to avoid precedence problems). > + > +#define ALL_B_ELEMENTS(i, wrlen)\ > +do {\ > +uint32_t i; \ > +for (i = wrlen / 8; i--;) eww... there's gotta be a nicer way. Is it really so long winded not to do directly? int i; for (i = 0; i < MSA_WRLEN/8; ++i) { } compared to what you have at the moment: ALL_B_ELEMENTS(i, MSA_WRLEN) { } DONE_ALL_ELEMENTS; It would be much more familiar/readable, and the ordering is explicit too (just in case it matters for any vector operations when source == destination) > +static inline void msa_move_v(void *pwd, void *pws) why not s/void/wr_t/? You could then presumably do *pwd = *pws > +{ > +ALL_D_ELEMENTS(i, MSA_WRLEN) { > +D(pwd, i) = D(pws, i); > +} DONE_ALL_ELEMENTS; > +} Cheers James
Re: [Qemu-devel] [PATCH 09/20] target-mips: add MSA branch instructions
Hi Yongbok, I know you're preparing another patchset, but thought I may as well continue reviewing this patchset until that one lands, sorry it's taken me a while to get round to it. On Mon, Jul 14, 2014 at 10:55:52AM +0100, Yongbok Kim wrote: > +static void determ_zero_element(TCGv tresult, uint8_t df, uint8_t wt) > +{ > +/* Note this function only works with MSA_WRLEN = 128 */ I reckon a quick comment to explain what this function is doing wouldn't hurt, since not obvious from name. I'm guessing from knowledge of MSA branches it determines whether there is a zero element. > +uint64_t eval_zero_or_big; > +uint64_t eval_big; > +switch (df) { > +case 0: /*DF_BYTE*/ > +eval_zero_or_big = 0x0101010101010101ULL; > +eval_big = 0x8080808080808080ULL; > +break; > +case 1: /*DF_HALF*/ > +eval_zero_or_big = 0x0001000100010001ULL; > +eval_big = 0x8000800080008000ULL; > +break; > +case 2: /*DF_WORD*/ > +eval_zero_or_big = 0x00010001ULL; > +eval_big = 0x80008000ULL; > +break; > +case 3: /*DF_DOUBLE*/ > +eval_zero_or_big = 0x0001ULL; > +eval_big = 0x8000ULL; > +break; > +} > +TCGv_i64 t0 = tcg_temp_local_new_i64(); > +TCGv_i64 t1 = tcg_temp_local_new_i64(); Variable declarations after code These don't need preserving over any branches, so presumably they don't need to be local temps. > +tcg_gen_subi_i64(t0, msa_wr_d[wt<<1], eval_zero_or_big); > +tcg_gen_andc_i64(t0, t0, msa_wr_d[wt<<1]); > +tcg_gen_andi_i64(t0, t0, eval_big); > +tcg_gen_subi_i64(t1, msa_wr_d[(wt<<1)+1], eval_zero_or_big); > +tcg_gen_andc_i64(t1, t1, msa_wr_d[(wt<<1)+1]); > +tcg_gen_andi_i64(t1, t1, eval_big); > +tcg_gen_or_i64(t0, t0, t1); > +/* if all bits is zero then all element is not zero */ nit: s/is/are/, s/element/elements/ > +/* if some bit is non-zero then some element is zero */ > +tcg_gen_setcondi_i64(TCG_COND_NE, t0, t0, 0); > +tcg_gen_trunc_i64_tl(tresult, t0); > +tcg_temp_free_i64(t0); > +tcg_temp_free_i64(t1); > +} > + > +static void gen_msa_branch(CPUMIPSState *env, DisasContext *ctx, uint32_t > op1) > +{ > +check_insn(ctx, ASE_MSA); > + > +if (ctx->hflags & MIPS_HFLAG_BMASK) { > +generate_exception(ctx, EXCP_RI); > +return; > +} > + > +uint8_t df = (ctx->opcode >> 21) & 0x3 /* df [22:21] */; > +uint8_t wt = (ctx->opcode >> 16) & 0x1f /* wt [20:16] */; The TRM on public website is wrong about the branch encoding! :-P > +int64_t s16 = (ctx->opcode >> 0) & 0x /* s16 [15:0] */; > +s16 = (s16 << 48) >> 48; /* sign extend s16 to 64 bits*/ declarations after code why not just use int16_t and let the compiler worry about sign extension? > + > +check_msa_access(env, ctx, wt, -1, -1); > + > +switch (op1) { > +case OPC_MSA_BZ_V: > +case OPC_MSA_BNZ_V: > +{ > +TCGv_i64 t0 = tcg_temp_local_new_i64(); i don't think this needs to be a local > +tcg_gen_or_i64(t0, msa_wr_d[wt<<1], msa_wr_d[(wt<<1)+1]); > +tcg_gen_setcondi_i64((op1 == OPC_MSA_BZ_V) ? > +TCG_COND_EQ : TCG_COND_NE, t0, t0, 0); > +tcg_gen_trunc_i64_tl(bcond, t0); > +tcg_temp_free_i64(t0); > +} > +break; > +case OPC_MSA_BZ_B: > +case OPC_MSA_BZ_H: > +case OPC_MSA_BZ_W: > +case OPC_MSA_BZ_D: > +determ_zero_element(bcond, df, wt); > +break; > +case OPC_MSA_BNZ_B: > +case OPC_MSA_BNZ_H: > +case OPC_MSA_BNZ_W: > +case OPC_MSA_BNZ_D: > +determ_zero_element(bcond, df, wt); > +tcg_gen_setcondi_tl(TCG_COND_EQ, bcond, bcond, 0); Might be slightly more efficient to just get determ_zero_element to generatee the correct condition in the first place. > +break; > +} > + > +int64_t offset = s16 << 2; declaration after code > +ctx->btarget = ctx->pc + offset + 4; > + > +ctx->hflags |= MIPS_HFLAG_BC; > +} blank line would be nice > static void decode_opc (CPUMIPSState *env, DisasContext *ctx) > { > int32_t offset; Cheers James
Re: [Qemu-devel] [PATCH 10/20] target-mips: add MSA I8 format instructions
(arg2 & dest), df) > + > +void helper_msa_bseli_b(CPUMIPSState *env, uint32_t wd, uint32_t ws, > +uint32_t i8) > +{ > +void *pwd = &(env->active_fpu.fpr[wd]); > +void *pws = &(env->active_fpu.fpr[ws]); > +ALL_B_ELEMENTS(i, MSA_WRLEN) { > +BIT_SELECT(B(pwd, i), B(pws, i), i8, DF_BYTE); > +} DONE_ALL_ELEMENTS; > +if (env->active_msa.msair & MSAIR_WRP_BIT) { > +env->active_msa.msamodify |= (1 << wd); > +} > +} I reckon the functions above could all be done easily enough in TCG by repeating i8 up to 64-bits (at translation time) and doing the operations on 64-bit quantities. Out of interest, was there a particular motivation to do it with helpers? In any case, that can always be an experiment for a later patch, and it all looks technically correct. Reviewed-by: James Hogan Cheers James
Re: [Qemu-devel] [PATCH v2 01/20] target-mips: add MSA defines and data structure
On Wed, Oct 29, 2014 at 01:41:49AM +, Yongbok Kim wrote: > diff --git a/target-mips/cpu.h b/target-mips/cpu.h > index 3b975eb..fb5abda 100644 > --- a/target-mips/cpu.h > +++ b/target-mips/cpu.h > +#define MSACSR_Flags2 > +#define MSACSR_CEF_MASK (0x << MSACSR_Flags) MSACSR_Flags is inconsistently named. Maybe MSACSR_CEF? Otherwise: Reviewed-by: James Hogan Cheers James
Re: [Qemu-devel] [PATCH v2 02/20] target-mips: add MSA exceptions
On Wed, Oct 29, 2014 at 01:41:50AM +, Yongbok Kim wrote: > add MSA exceptions > > Signed-off-by: Yongbok Kim Reviewed-by: James Hogan Cheers James > --- > target-mips/helper.c | 10 ++ > 1 files changed, 10 insertions(+), 0 deletions(-) > > diff --git a/target-mips/helper.c b/target-mips/helper.c > index c92b25c..3a93c20 100644 > --- a/target-mips/helper.c > +++ b/target-mips/helper.c > @@ -426,6 +426,8 @@ static const char * const excp_names[EXCP_LAST + 1] = { > [EXCP_CACHE] = "cache error", > [EXCP_TLBXI] = "TLB execute-inhibit", > [EXCP_TLBRI] = "TLB read-inhibit", > +[EXCP_MSADIS] = "MSA disabled", > +[EXCP_MSAFPE] = "MSA floating point", > }; > > target_ulong exception_resume_pc (CPUMIPSState *env) > @@ -667,6 +669,10 @@ void mips_cpu_do_interrupt(CPUState *cs) > cause = 13; > update_badinstr = 1; > goto set_EPC; > +case EXCP_MSAFPE: > +cause = 14; > +update_badinstr = 1; > +goto set_EPC; > case EXCP_FPE: > cause = 15; > update_badinstr = 1; > @@ -681,6 +687,10 @@ void mips_cpu_do_interrupt(CPUState *cs) > case EXCP_TLBXI: > cause = 20; > goto set_EPC; > +case EXCP_MSADIS: > +cause = 21; > +update_badinstr = 1; > +goto set_EPC; > case EXCP_MDMX: > cause = 22; > goto set_EPC; > -- > 1.7.4 > >
Re: [Qemu-devel] [PATCH v2 03/20] target-mips: remove duplicated mips/ieee mapping function
On Wed, Oct 29, 2014 at 01:41:51AM +, Yongbok Kim wrote: > > Signed-off-by: Yongbok Kim A more verbose commit message wouldn't hurt. I.e. this patch does two things, it removes the duplicate ieee_rm in gdbstub.c, but it also makes ieee_ex_to_mips() available to msa_helper.c as well as op_helper.c. Otherwise, Reviewed-by: James Hogan Cheers James > --- > target-mips/cpu.h |4 > target-mips/gdbstub.c |7 --- > target-mips/op_helper.c |4 ++-- > 3 files changed, 6 insertions(+), 9 deletions(-) > > diff --git a/target-mips/cpu.h b/target-mips/cpu.h > index fb5abda..6d3db79 100644 > --- a/target-mips/cpu.h > +++ b/target-mips/cpu.h > @@ -760,6 +760,10 @@ hwaddr cpu_mips_translate_address (CPUMIPSState *env, > target_ulong address, > #endif > target_ulong exception_resume_pc (CPUMIPSState *env); > > +/* op_helper.c */ > +extern unsigned int ieee_rm[]; > +int ieee_ex_to_mips(int xcpt); > + > static inline void cpu_get_tb_cpu_state(CPUMIPSState *env, target_ulong *pc, > target_ulong *cs_base, int *flags) > { > diff --git a/target-mips/gdbstub.c b/target-mips/gdbstub.c > index 5b72d58..f65fec2 100644 > --- a/target-mips/gdbstub.c > +++ b/target-mips/gdbstub.c > @@ -73,13 +73,6 @@ int mips_cpu_gdb_read_register(CPUState *cs, uint8_t > *mem_buf, int n) > return 0; > } > > -/* convert MIPS rounding mode in FCR31 to IEEE library */ > -static unsigned int ieee_rm[] = { > -float_round_nearest_even, > -float_round_to_zero, > -float_round_up, > -float_round_down > -}; > #define RESTORE_ROUNDING_MODE \ > set_float_rounding_mode(ieee_rm[env->active_fpu.fcr31 & 3], \ > &env->active_fpu.fp_status) > diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c > index 0c75ec8..7cbf4cf 100644 > --- a/target-mips/op_helper.c > +++ b/target-mips/op_helper.c > @@ -2340,7 +2340,7 @@ void mips_cpu_unassigned_access(CPUState *cs, hwaddr > addr, > #define FP_TO_INT64_OVERFLOW 0x7fffULL > > /* convert MIPS rounding mode in FCR31 to IEEE library */ > -static unsigned int ieee_rm[] = { > +unsigned int ieee_rm[] = { > float_round_nearest_even, > float_round_to_zero, > float_round_up, > @@ -2461,7 +2461,7 @@ void helper_ctc1(CPUMIPSState *env, target_ulong arg1, > uint32_t fs, uint32_t rt) > do_raise_exception(env, EXCP_FPE, GETPC()); > } > > -static inline int ieee_ex_to_mips(int xcpt) > +int ieee_ex_to_mips(int xcpt) > { > int ret = 0; > if (xcpt) { > -- > 1.7.4 > >
Re: [Qemu-devel] [PATCH v2 04/20] target-mips: add 16, 64 bit load and store
On Wed, Oct 29, 2014 at 01:41:52AM +, Yongbok Kim wrote: > > Signed-off-by: Yongbok Kim You seem to have lost the commit message compared to v1. Patch looks fine to me, but IMO it's worth squashing this into patch 18, since that's the only place they're used. Cheers James > --- > target-mips/op_helper.c |7 +++ > 1 files changed, 3 insertions(+), 4 deletions(-) > > diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c > index 7cbf4cf..e878442 100644 > --- a/target-mips/op_helper.c > +++ b/target-mips/op_helper.c > @@ -90,10 +90,10 @@ static inline type do_##name(CPUMIPSState *env, > target_ulong addr, \ > } \ > } > #endif > +HELPER_LD(lbu, ldub, uint8_t) > +HELPER_LD(lhu, lduw, uint16_t) > HELPER_LD(lw, ldl, int32_t) > -#ifdef TARGET_MIPS64 > HELPER_LD(ld, ldq, int64_t) > -#endif > #undef HELPER_LD > > #if defined(CONFIG_USER_ONLY) > @@ -118,10 +118,9 @@ static inline void do_##name(CPUMIPSState *env, > target_ulong addr, \ > } > #endif > HELPER_ST(sb, stb, uint8_t) > +HELPER_ST(sh, stw, uint16_t) > HELPER_ST(sw, stl, uint32_t) > -#ifdef TARGET_MIPS64 > HELPER_ST(sd, stq, uint64_t) > -#endif > #undef HELPER_ST > > target_ulong helper_clo (target_ulong arg1) > -- > 1.7.4 > >
Re: [Qemu-devel] [PATCH v2 05/20] target-mips: stop translation after ctc1
On Wed, Oct 29, 2014 at 01:41:53AM +, Yongbok Kim wrote: > stop translation as ctc1 instruction can change hflags > > Signed-off-by: Yongbok Kim Reviewed-by: James Hogan Cheers James > --- > target-mips/translate.c |6 ++ > 1 files changed, 6 insertions(+), 0 deletions(-) > > diff --git a/target-mips/translate.c b/target-mips/translate.c > index 9a8f5c9..b388ba5 100644 > --- a/target-mips/translate.c > +++ b/target-mips/translate.c > @@ -7490,12 +7490,15 @@ static void gen_mttr(CPUMIPSState *env, DisasContext > *ctx, int rd, int rt, > break; > case 3: > /* XXX: For now we support only a single FPU context. */ > +save_cpu_state(ctx, 1); > { > TCGv_i32 fs_tmp = tcg_const_i32(rd); > > gen_helper_0e2i(ctc1, t0, fs_tmp, rt); > tcg_temp_free_i32(fs_tmp); > } > +/* Stop translation as we may have changed hflags */ > +ctx->bstate = BS_STOP; > break; > /* COP2: Not implemented. */ > case 4: > @@ -8089,12 +8092,15 @@ static void gen_cp1 (DisasContext *ctx, uint32_t opc, > int rt, int fs) > break; > case OPC_CTC1: > gen_load_gpr(t0, rt); > +save_cpu_state(ctx, 1); > { > TCGv_i32 fs_tmp = tcg_const_i32(fs); > > gen_helper_0e2i(ctc1, t0, fs_tmp, rt); > tcg_temp_free_i32(fs_tmp); > } > +/* Stop translation as we may have changed hflags */ > +ctx->bstate = BS_STOP; > opn = "ctc1"; > break; > #if defined(TARGET_MIPS64) > -- > 1.7.4 > >
Re: [Qemu-devel] [PATCH v2 07/20] target-mips: add msa_reset(), global msa register
On Wed, Oct 29, 2014 at 01:41:55AM +, Yongbok Kim wrote: > add msa_reset() and global msa register (d type only) > > Signed-off-by: Yongbok Kim Reviewed-by: James Hogan Cheers James > --- > target-mips/translate.c | 56 > ++ > target-mips/translate_init.c | 35 ++ > 2 files changed, 91 insertions(+), 0 deletions(-) > > diff --git a/target-mips/translate.c b/target-mips/translate.c > index 555f89b..f1160aa 100644 > --- a/target-mips/translate.c > +++ b/target-mips/translate.c > @@ -1356,6 +1356,7 @@ static TCGv cpu_dspctrl, btarget, bcond; > static TCGv_i32 hflags; > static TCGv_i32 fpu_fcr0, fpu_fcr31; > static TCGv_i64 fpu_f64[32]; > +static TCGv_i64 msa_wr_d[64]; > > static uint32_t gen_opc_hflags[OPC_BUF_SIZE]; > static target_ulong gen_opc_btarget[OPC_BUF_SIZE]; > @@ -1454,6 +1455,25 @@ static const char * const fregnames[] = { > "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", > }; > > +static const char * const msaregnames[] = { > +"w0.d0", "w0.d1", "w1.d0", "w1.d1", > +"w2.d0", "w2.d1", "w3.d0", "w3.d1", > +"w4.d0", "w4.d1", "w5.d0", "w5.d1", > +"w6.d0", "w6.d1", "w7.d0", "w7.d1", > +"w8.d0", "w8.d1", "w9.d0", "w9.d1", > +"w10.d0", "w10.d1", "w11.d0", "w11.d1", > +"w12.d0", "w12.d1", "w13.d0", "w13.d1", > +"w14.d0", "w14.d1", "w15.d0", "w15.d1", > +"w16.d0", "w16.d1", "w17.d0", "w17.d1", > +"w18.d0", "w18.d1", "w19.d0", "w19.d1", > +"w20.d0", "w20.d1", "w21.d0", "w21.d1", > +"w22.d0", "w22.d1", "w23.d0", "w23.d1", > +"w24.d0", "w24.d1", "w25.d0", "w25.d1", > +"w26.d0", "w26.d1", "w27.d0", "w27.d1", > +"w28.d0", "w28.d1", "w29.d0", "w29.d1", > +"w30.d0", "w30.d1", "w31.d0", "w31.d1", > +}; > + > #define MIPS_DEBUG(fmt, ...) > \ > do { > \ > if (MIPS_DEBUG_DISAS) { > \ > @@ -17206,6 +17226,27 @@ static void decode_opc_special3(CPUMIPSState *env, > DisasContext *ctx) > } > } > > +/* MIPS SIMD Architecture (MSA) */ > +static inline int check_msa_access(CPUMIPSState *env, DisasContext *ctx) > +{ > +if (unlikely((ctx->hflags & MIPS_HFLAG_FPU) && > + !(ctx->hflags & MIPS_HFLAG_F64))) { > +generate_exception(ctx, EXCP_RI); > +return 0; > +} > + > +if (unlikely(!(ctx->hflags & MIPS_HFLAG_MSA))) { > +if (ctx->insn_flags & ASE_MSA) { > +generate_exception(ctx, EXCP_MSADIS); > +return 0; > +} else { > +generate_exception(ctx, EXCP_RI); > +return 0; > +} > +} > +return 1; > +} > + > static void decode_opc (CPUMIPSState *env, DisasContext *ctx) > { > int32_t offset; > @@ -18136,6 +18177,15 @@ void mips_tcg_init(void) > fpu_f64[i] = tcg_global_mem_new_i64(TCG_AREG0, off, fregnames[i]); > } > > +for (i = 0; i < 32; i++) { > +int off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[0]); > +msa_wr_d[i * 2] = > +tcg_global_mem_new_i64(TCG_AREG0, off, msaregnames[i * 2]); > +off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[1]); > +msa_wr_d[i * 2 + 1] = > +tcg_global_mem_new_i64(TCG_AREG0, off, msaregnames[i * 2 + > 1]); > +} > + > cpu_PC = tcg_global_mem_new(TCG_AREG0, > offsetof(CPUMIPSState, active_tc.PC), "PC"); > for (i = 0; i < MIPS_DSP_ACC; i++) { > @@ -18243,6 +18293,7 @@ void cpu_state_reset(CPUMIPSState *env) > env->CP0_PageGrain_rw_bitmask = env->cpu_model->CP0_PageGrain_rw_bitmask; > env->CP0_PageGrain = env->cpu_model->CP0_PageGrain; > env->active_fpu.fcr0 = env->cpu_model-&g
Re: [Qemu-devel] [PATCH v2 08/20] target-mips: add msa_helper.c
On Wed, Oct 29, 2014 at 01:41:56AM +, Yongbok Kim wrote: > add msa_helper.c > > Signed-off-by: Yongbok Kim Reviewed-by: James Hogan Cheers James > --- > target-mips/Makefile.objs |2 +- > target-mips/msa_helper.c | 49 > + > 2 files changed, 50 insertions(+), 1 deletions(-) > create mode 100644 target-mips/msa_helper.c > > diff --git a/target-mips/Makefile.objs b/target-mips/Makefile.objs > index 716244f..108fd9b 100644 > --- a/target-mips/Makefile.objs > +++ b/target-mips/Makefile.objs > @@ -1,4 +1,4 @@ > obj-y += translate.o dsp_helper.o op_helper.o lmi_helper.o helper.o cpu.o > -obj-y += gdbstub.o > +obj-y += gdbstub.o msa_helper.o > obj-$(CONFIG_SOFTMMU) += machine.o > obj-$(CONFIG_KVM) += kvm.o > diff --git a/target-mips/msa_helper.c b/target-mips/msa_helper.c > new file mode 100644 > index 000..b65fb27 > --- /dev/null > +++ b/target-mips/msa_helper.c > @@ -0,0 +1,49 @@ > +/* > + * MIPS SIMD Architecture Module Instruction emulation helpers for QEMU. > + * > + * Copyright (c) 2014 Imagination Technologies > + * > + * This library is free software; you can redistribute it and/or > + * modify it under the terms of the GNU Lesser General Public > + * License as published by the Free Software Foundation; either > + * version 2 of the License, or (at your option) any later version. > + * > + * This library 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 > + * Lesser General Public License for more details. > + * > + * You should have received a copy of the GNU Lesser General Public > + * License along with this library; if not, see > <http://www.gnu.org/licenses/>. > + */ > + > +#include "cpu.h" > +#include "exec/helper-proto.h" > + > +/* Data format min and max values */ > +#define DF_BITS(df) (1 << ((df) + 3)) > + > +#define DF_MAX_INT(df) (int64_t)((1LL << (DF_BITS(df) - 1)) - 1) > +#define M_MAX_INT(m)(int64_t)((1LL << ((m) - 1)) - 1) > + > +#define DF_MIN_INT(df) (int64_t)(-(1LL << (DF_BITS(df) - 1))) > +#define M_MIN_INT(m)(int64_t)(-(1LL << ((m) - 1))) > + > +#define DF_MAX_UINT(df) (uint64_t)(-1ULL >> (64 - DF_BITS(df))) > +#define M_MAX_UINT(m) (uint64_t)(-1ULL >> (64 - (m))) > + > +#define UNSIGNED(x, df) ((x) & DF_MAX_UINT(df)) > +#define SIGNED(x, df) \ > +int64_t)x) << (64 - DF_BITS(df))) >> (64 - DF_BITS(df))) > + > +/* Element-by-element access macros */ > +#define DF_ELEMENTS(df) (MSA_WRLEN / DF_BITS(df)) > + > +static inline void msa_move_v(wr_t *pwd, wr_t *pws) > +{ > +uint32_t i; > + > +for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) { > +pwd->d[i] = pws->d[i]; > +} > +} > -- > 1.7.4 > >
Re: [Qemu-devel] [PATCH v2 09/20] target-mips: add MSA branch instructions
On Wed, Oct 29, 2014 at 01:41:57AM +, Yongbok Kim wrote: > add MSA branch instructions > > Signed-off-by: Yongbok Kim Reviewed-by: James Hogan Cheers James > --- > target-mips/translate.c | 333 > +++ > 1 files changed, 219 insertions(+), 114 deletions(-) > > diff --git a/target-mips/translate.c b/target-mips/translate.c > index f1160aa..0df86cc 100644 > --- a/target-mips/translate.c > +++ b/target-mips/translate.c > @@ -17247,6 +17247,92 @@ static inline int check_msa_access(CPUMIPSState > *env, DisasContext *ctx) > return 1; > } > > +static void gen_check_zero_element(TCGv tresult, uint8_t df, uint8_t wt) > +{ > +/* generates tcg ops to check if any element is 0 */ > +/* Note this function only works with MSA_WRLEN = 128 */ > +uint64_t eval_zero_or_big = 0; > +uint64_t eval_big = 0; > +TCGv_i64 t0 = tcg_temp_new_i64(); > +TCGv_i64 t1 = tcg_temp_new_i64(); > +switch (df) { > +case DF_BYTE: > +eval_zero_or_big = 0x0101010101010101ULL; > +eval_big = 0x8080808080808080ULL; > +break; > +case DF_HALF: > +eval_zero_or_big = 0x0001000100010001ULL; > +eval_big = 0x8000800080008000ULL; > +break; > +case DF_WORD: > +eval_zero_or_big = 0x00010001ULL; > +eval_big = 0x80008000ULL; > +break; > +case DF_DOUBLE: > +eval_zero_or_big = 0x0001ULL; > +eval_big = 0x8000ULL; > +break; > +} > +tcg_gen_subi_i64(t0, msa_wr_d[wt<<1], eval_zero_or_big); > +tcg_gen_andc_i64(t0, t0, msa_wr_d[wt<<1]); > +tcg_gen_andi_i64(t0, t0, eval_big); > +tcg_gen_subi_i64(t1, msa_wr_d[(wt<<1)+1], eval_zero_or_big); > +tcg_gen_andc_i64(t1, t1, msa_wr_d[(wt<<1)+1]); > +tcg_gen_andi_i64(t1, t1, eval_big); > +tcg_gen_or_i64(t0, t0, t1); > +/* if all bits are zero then all elements are not zero */ > +/* if some bit is non-zero then some element is zero */ > +tcg_gen_setcondi_i64(TCG_COND_NE, t0, t0, 0); > +tcg_gen_trunc_i64_tl(tresult, t0); > +tcg_temp_free_i64(t0); > +tcg_temp_free_i64(t1); > +} > + > +static void gen_msa_branch(CPUMIPSState *env, DisasContext *ctx, uint32_t > op1) > +{ > +uint8_t df = (ctx->opcode >> 21) & 0x3; > +uint8_t wt = (ctx->opcode >> 16) & 0x1f; > +int64_t s16 = (int16_t)ctx->opcode; > + > +check_msa_access(env, ctx); > + > +if (ctx->insn_flags & ISA_MIPS32R6 && ctx->hflags & MIPS_HFLAG_BMASK) { > +MIPS_DEBUG("CTI in delay / forbidden slot"); > +generate_exception(ctx, EXCP_RI); > +return; > +} > +switch (op1) { > +case OPC_BZ_V: > +case OPC_BNZ_V: > +{ > +TCGv_i64 t0 = tcg_temp_new_i64(); > +tcg_gen_or_i64(t0, msa_wr_d[wt<<1], msa_wr_d[(wt<<1)+1]); > +tcg_gen_setcondi_i64((op1 == OPC_BZ_V) ? > +TCG_COND_EQ : TCG_COND_NE, t0, t0, 0); > +tcg_gen_trunc_i64_tl(bcond, t0); > +tcg_temp_free_i64(t0); > +} > +break; > +case OPC_BZ_B: > +case OPC_BZ_H: > +case OPC_BZ_W: > +case OPC_BZ_D: > +gen_check_zero_element(bcond, df, wt); > +break; > +case OPC_BNZ_B: > +case OPC_BNZ_H: > +case OPC_BNZ_W: > +case OPC_BNZ_D: > +gen_check_zero_element(bcond, df, wt); > +tcg_gen_setcondi_tl(TCG_COND_EQ, bcond, bcond, 0); > +break; > +} > + > +ctx->btarget = ctx->pc + (s16 << 2) + 4; > + > +ctx->hflags |= MIPS_HFLAG_BC; > +ctx->hflags |= MIPS_HFLAG_BDS32; > +} > static void decode_opc (CPUMIPSState *env, DisasContext *ctx) > { > int32_t offset; > @@ -17568,133 +17654,152 @@ static void decode_opc (CPUMIPSState *env, > DisasContext *ctx) > break; > > case OPC_CP1: > -if (ctx->CP0_Config1 & (1 << CP0C1_FP)) { > +op1 = MASK_CP1(ctx->opcode); > + > +switch (op1) { > +case OPC_MFHC1: > +case OPC_MTHC1: > check_cp1_enabled(ctx); > -op1 = MASK_CP1(ctx->opcode); > -switch (op1) { > -case OPC_MFHC1: > -case OPC_MTHC1: > -check_insn(ctx, ISA_MIPS32R2); > -case OPC_MFC1: > -case OPC_CFC1: > -case OPC_MTC1: > -case OPC_CTC1: > -gen_cp1(ctx, op1, rt, rd); > -
Re: [Qemu-devel] [PATCH v2 10/20] target-mips: add MSA I8 format instructions
On Wed, Oct 29, 2014 at 01:41:58AM +, Yongbok Kim wrote: > add MSA I8 format instructions > > Reviewed-by: James Hogan The patch has changed quite a lot, so probably worth dropping Reviewed-by in those cases in future. > Signed-off-by: Yongbok Kim > +#define MSA_FN_IMM8(FUNC, DEST, OPERATION) \ > +void helper_msa_ ## FUNC(CPUMIPSState *env, uint32_t wd, uint32_t ws, \ > +uint32_t i8)\ > +{ \ > +wr_t *pwd = &(env->active_fpu.fpr[wd].wr); \ > +wr_t *pws = &(env->active_fpu.fpr[ws].wr); \ > +uint32_t i; \ > +for (i = 0; i < DF_ELEMENTS(DF_BYTE); i++) {\ > +DEST = OPERATION; \ > +} \ I presume register partitioning isn't going to be supported in this round of patches? Okay. > +} > + > +MSA_FN_IMM8(andi_b, pwd->b[i], pws->b[i] & i8) > +MSA_FN_IMM8(ori_b, pwd->b[i], pws->b[i] | i8) > +MSA_FN_IMM8(nori_b, pwd->b[i], ~(pws->b[i] | i8)) > +MSA_FN_IMM8(xori_b, pwd->b[i], pws->b[i] ^ i8) > + > +#define BIT_MOVE_IF_NOT_ZERO(dest, arg1, arg2, df) \ > +UNSIGNED(((dest & (~arg2)) | (arg1 & arg2)), df) > +MSA_FN_IMM8(bmnzi_b, pwd->b[i], \ no need to escape the newline > +BIT_MOVE_IF_NOT_ZERO(pwd->b[i], pws->b[i], i8, DF_BYTE)) > + > +#define BIT_MOVE_IF_ZERO(dest, arg1, arg2, df) \ > +UNSIGNED((dest & arg2) | (arg1 & (~arg2)), df) > +MSA_FN_IMM8(bmzi_b, pwd->b[i], \ same > +BIT_MOVE_IF_ZERO(pwd->b[i], pws->b[i], i8, DF_BYTE)) > + > +#define BIT_SELECT(dest, arg1, arg2, df) \ > +UNSIGNED((arg1 & (~dest)) | (arg2 & dest), df) > +MSA_FN_IMM8(bseli_b, pwd->b[i], \ same > +BIT_SELECT(pwd->b[i], pws->b[i], i8, DF_BYTE)) > + > +#undef MSA_FN_IMM8 > + > +#define SHF_POS(i, imm) ((i & 0xfc) + ((imm >> (2 * (i & 0x03))) & 0x03)) Should probably put brackets around macro arguments here, just for the sake of robustness. Otherwise Reviewed-by: James Hogan Cheers James
Re: [Qemu-devel] [PATCH v2 11/20] target-mips: add MSA I5 format instruction
Hi Yongbok, On Wed, Oct 29, 2014 at 01:41:59AM +, Yongbok Kim wrote: > +DEF_HELPER_5(msa_addvi_df, void, env, i32, i32, i32, s64) > +DEF_HELPER_5(msa_ceqi_df, void, env, i32, i32, i32, s64) > +DEF_HELPER_5(msa_clei_s_df, void, env, i32, i32, i32, s64) > +DEF_HELPER_5(msa_clei_u_df, void, env, i32, i32, i32, s64) > +DEF_HELPER_5(msa_clti_s_df, void, env, i32, i32, i32, s64) > +DEF_HELPER_5(msa_clti_u_df, void, env, i32, i32, i32, s64) > +DEF_HELPER_4(msa_ldi_df, void, env, i32, i32, i32) > +DEF_HELPER_5(msa_maxi_s_df, void, env, i32, i32, i32, s64) > +DEF_HELPER_5(msa_maxi_u_df, void, env, i32, i32, i32, s64) > +DEF_HELPER_5(msa_mini_s_df, void, env, i32, i32, i32, s64) > +DEF_HELPER_5(msa_mini_u_df, void, env, i32, i32, i32, s64) > +DEF_HELPER_5(msa_subvi_df, void, env, i32, i32, i32, s64) s64 seems like overkill for a 5bit field. > diff --git a/target-mips/msa_helper.c b/target-mips/msa_helper.c > index 46ffaa5..ffdde07 100644 > --- a/target-mips/msa_helper.c > +++ b/target-mips/msa_helper.c > @@ -114,3 +114,145 @@ void helper_msa_shf_df(CPUMIPSState *env, uint32_t df, > uint32_t wd, > msa_move_v(pwd, pwx); > } > > +static inline int64_t msa_addv_df(uint32_t df, int64_t arg1, int64_t arg2) > +{ > +return arg1 + arg2; > +} > + > +static inline int64_t msa_subv_df(uint32_t df, int64_t arg1, int64_t arg2) > +{ > +return arg1 - arg2; > +} > + > +static inline int64_t msa_ceq_df(uint32_t df, int64_t arg1, int64_t arg2) > +{ > +return arg1 == arg2 ? -1 : 0; > +} > + > +static inline int64_t msa_cle_s_df(uint32_t df, int64_t arg1, int64_t arg2) > +{ > +return arg1 <= arg2 ? -1 : 0; > +} > + > +static inline int64_t msa_cle_u_df(uint32_t df, int64_t arg1, int64_t arg2) > +{ > +uint64_t u_arg1 = UNSIGNED(arg1, df); > +uint64_t u_arg2 = UNSIGNED(arg2, df); > +return u_arg1 <= u_arg2 ? -1 : 0; > +} > + > +static inline int64_t msa_clt_s_df(uint32_t df, int64_t arg1, int64_t arg2) > +{ > +return arg1 < arg2 ? -1 : 0; > +} > + > +static inline int64_t msa_clt_u_df(uint32_t df, int64_t arg1, int64_t arg2) > +{ > +uint64_t u_arg1 = UNSIGNED(arg1, df); > +uint64_t u_arg2 = UNSIGNED(arg2, df); > +return u_arg1 < u_arg2 ? -1 : 0; > +} > + > +static inline int64_t msa_max_s_df(uint32_t df, int64_t arg1, int64_t arg2) > +{ > +return arg1 > arg2 ? arg1 : arg2; > +} > + > +static inline int64_t msa_max_u_df(uint32_t df, int64_t arg1, int64_t arg2) > +{ > +uint64_t u_arg1 = UNSIGNED(arg1, df); > +uint64_t u_arg2 = UNSIGNED(arg2, df); > +return u_arg1 > u_arg2 ? arg1 : arg2; > +} > + > +static inline int64_t msa_min_s_df(uint32_t df, int64_t arg1, int64_t arg2) > +{ > +return arg1 < arg2 ? arg1 : arg2; > +} > + > +static inline int64_t msa_min_u_df(uint32_t df, int64_t arg1, int64_t arg2) > +{ > +uint64_t u_arg1 = UNSIGNED(arg1, df); > +uint64_t u_arg2 = UNSIGNED(arg2, df); > +return u_arg1 < u_arg2 ? arg1 : arg2; > +} > + > +#define MSA_BINOP_IMM_DF(helper, func) \ > +void helper_msa_ ## helper ## _df(CPUMIPSState *env, uint32_t df, \ > +uint32_t wd, uint32_t ws, int64_t u5) \ > +{ \ > +wr_t *pwd = &(env->active_fpu.fpr[wd].wr); \ > +wr_t *pws = &(env->active_fpu.fpr[ws].wr); \ > +uint32_t i; \ > +\ > +switch (df) { \ > +case DF_BYTE: \ > +for (i = 0; i < DF_ELEMENTS(DF_BYTE); i++) {\ > +pwd->b[i] = msa_ ## func ## _df(df, pws->b[i], u5); \ > +} \ > +break; \ > +case DF_HALF: \ > +for (i = 0; i < DF_ELEMENTS(DF_HALF); i++) {\ > +pwd->h[i] = msa_ ## func ## _df(df, pws->h[i], u5); \ > +} \ > +break; \ > +case DF_WORD: \ > +for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) {\ > +pwd->w[i] = msa_ ## func ## _df(df, pws->w[i], u5); \ > +} \ > +break; \ > +case DF_DOUBLE: \ > +for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) { \ > +pwd->d[i] = msa_ ## func ## _df(df, pw
Re: [Qemu-devel] [PATCH v2] target-mips: fix broken MIPS16 and microMIPS
On Tue, Jul 01, 2014 at 05:43:05PM +0100, Yongbok Kim wrote: > Commit 240ce26a broke MIPS16 and microMIPS support as it didn't > care those branches and jumps don't have delay slot in > MIPS16 and microMIPS. > > This patch introduces a new argument delayslot_size to the > gen_compute_branch() indicating size of delay slot {0, 2, 4}. > And the information is used to call handle_delay_slot() forcingly > when no delay slot is required. > > There are some microMIPS branch and jump instructions that requires > exact size of instruction in the delay slot. For indicating > these instructions, MIPS_HFLAG_BDS_STRICT flag is introduced. > > Those fictional branch opcodes defined to support MIPS16 and > microMIPS are no longer needed. > > Signed-off-by: Yongbok Kim Jonas hit this problem too with a mips16 enabled userland, and has confirmed that this patch fixes it: Tested-by: Jonas Gorski Cheers James > --- > v2: > * correct MIPS_HFLAG_TMASK > --- > target-mips/cpu.h | 13 +- > target-mips/translate.c | 284 > ++- > 2 files changed, 117 insertions(+), 180 deletions(-) > > diff --git a/target-mips/cpu.h b/target-mips/cpu.h > index 8b9a92e..c81dfac 100644 > --- a/target-mips/cpu.h > +++ b/target-mips/cpu.h > @@ -431,7 +431,7 @@ struct CPUMIPSState { > int error_code; > uint32_t hflags;/* CPU State */ > /* TMASK defines different execution modes */ > -#define MIPS_HFLAG_TMASK 0xC07FF > +#define MIPS_HFLAG_TMASK 0x1807FF > #define MIPS_HFLAG_MODE 0x7 /* execution modes*/ > /* The KSU flags must be the lowest bits in hflags. The flag order > must be the same as defined for CP0 Status. This allows to use > @@ -463,17 +463,18 @@ struct CPUMIPSState { > #define MIPS_HFLAG_BL 0x01800 /* Likely branch */ > #define MIPS_HFLAG_BR 0x02000 /* branch to register (can't link TB) */ > /* Extra flags about the current pending branch. */ > -#define MIPS_HFLAG_BMASK_EXT 0x3C000 > +#define MIPS_HFLAG_BMASK_EXT 0x7C000 > #define MIPS_HFLAG_B160x04000 /* branch instruction was 16 bits */ > #define MIPS_HFLAG_BDS16 0x08000 /* branch requires 16-bit delay slot */ > #define MIPS_HFLAG_BDS32 0x1 /* branch requires 32-bit delay slot */ > -#define MIPS_HFLAG_BX 0x2 /* branch exchanges execution mode*/ > +#define MIPS_HFLAG_BDS_STRICT 0x2 /* Strict delay slot size */ > +#define MIPS_HFLAG_BX 0x4 /* branch exchanges execution mode*/ > #define MIPS_HFLAG_BMASK (MIPS_HFLAG_BMASK_BASE | MIPS_HFLAG_BMASK_EXT) > /* MIPS DSP resources access. */ > -#define MIPS_HFLAG_DSP 0x4 /* Enable access to MIPS DSP resources. */ > -#define MIPS_HFLAG_DSPR2 0x8 /* Enable access to MIPS DSPR2 resources. > */ > +#define MIPS_HFLAG_DSP 0x08 /* Enable access to MIPS DSP resources. */ > +#define MIPS_HFLAG_DSPR2 0x10 /* Enable access to MIPS DSPR2 resources. > */ > /* Extra flag about HWREna register. */ > -#define MIPS_HFLAG_HWRENA_ULR 0x10 /* ULR bit from HWREna is set. */ > +#define MIPS_HFLAG_HWRENA_ULR 0x20 /* ULR bit from HWREna is set. */ > target_ulong btarget;/* Jump / branch target */ > target_ulong bcond; /* Branch condition (if needed) */ > > diff --git a/target-mips/translate.c b/target-mips/translate.c > index 2f91959..a654ae8 100644 > --- a/target-mips/translate.c > +++ b/target-mips/translate.c > @@ -61,7 +61,6 @@ enum { > /* Jump and branches */ > OPC_J= (0x02 << 26), > OPC_JAL = (0x03 << 26), > -OPC_JALS = OPC_JAL | 0x5, > OPC_BEQ = (0x04 << 26), /* Unconditional if rs = rt = 0 (B) */ > OPC_BEQL = (0x14 << 26), > OPC_BNE = (0x05 << 26), > @@ -70,8 +69,7 @@ enum { > OPC_BLEZL= (0x16 << 26), > OPC_BGTZ = (0x07 << 26), > OPC_BGTZL= (0x17 << 26), > -OPC_JALX = (0x1D << 26), /* MIPS 16 only */ > -OPC_JALXS= OPC_JALX | 0x5, > +OPC_JALX = (0x1D << 26), > /* Load and stores */ > OPC_LDL = (0x1A << 26), > OPC_LDR = (0x1B << 26), > @@ -171,8 +169,6 @@ enum { > /* Jumps */ > OPC_JR = 0x08 | OPC_SPECIAL, /* Also JR.HB */ > OPC_JALR = 0x09 | OPC_SPECIAL, /* Also JALR.HB */ > -OPC_JALRC= OPC_JALR | (0x5 << 6), > -OPC_JALRS= 0x10 | OPC_SPECIAL | (0x5 << 6), > /* Traps */ > OPC_TGE = 0x30 | OPC_SPECIAL, > OPC_TGEU = 0x31 | OPC_SPECIAL, > @@ -236,10 +232,8 @@ enum { > OPC_BGEZ = (0x01 << 16) | OPC_REGIMM, > OPC_BGEZL= (0x03 << 16) | OPC_REGIMM, > OPC_BLTZAL = (0x10 << 16) | OPC_REGIMM, > -OPC_BLTZALS = OPC_BLTZAL | 0x5, /* microMIPS */ > OPC_BLTZALL = (0x12 << 16) | OPC_REGIMM, > OPC_BGEZAL = (0x11 << 16) | OPC_REGIMM, > -OPC_BGEZALS = OPC_BGEZAL | 0x5, /* microMIPS */ > OPC_BGEZALL = (0x13 << 16) | OPC_REGIMM,
Re: [Qemu-devel] [PATCH v5 00/12] KVM Support for MIPS32 Processors
Hi Peter, On 10/07/14 13:17, Peter Maydell wrote: > On 17 June 2014 23:10, James Hogan wrote: >> The patchset depends on v4 of "target-mips: implement UserLocal >> Register". I'm aiming for QEMU 2.1, hopefully it isn't too late to get >> some final review. >> >> Thanks to everybody who has already taken part in review. >> >> This patchset implements KVM support for MIPS32 processors, using Trap & >> Emulation. > > I was looking at what happens for MMIO accesses to nonexistent > memory when we're running under KVM, and interestingly this > patchset means MIPS is now the only CPU which both (a) supports > KVM and (b) has an implementation of the do_unassigned_access() > CPU hook. Does the current code support a guest attempt to > access unassigned physical addresses? I had a look at the code > and it seems like mips_cpu_unassigned_access() will end up > calling cpu_restore_state() and cpu_loop_exit(), which I think > will probably crash if you call them when using KVM rather than > TCG... Yes, I have observed this in the past when experimentally writing to the Malta reset region from the guest (see the patch "mips/malta: allow volatile writes to reset flash" which didn't get applied but worked around the specific issue). That was because read only memory regions were treated as unassigned from the point of view of writes (which tbh seems wrong), but it could happen with any unassigned access > 0x8000 from the guest AFAICT. So yeh, until mips_cpu_unassigned_access does something more portable for KVM, conditionally setting do_unassigned_access only if !kvm_enabled() looks sensible. I'll see if I can reproduce it and submit a patch. > More generally, there doesn't really seem to be provision in the > KVM KVM_EXIT_MMIO API for returning "this access failed". > I guess in theory userspace could do all the "figure out how > to adjust CPU state to do exception entry and then run VCPU", > but that seems like quite a lot of work which the kernel already > knows how to do; is there some way to provide a simpler API > that lets userspace just inform the kernel that it needs to > fault the access? Indeed. Paolo's idea would work well I think. A data bus error exception would likely be the only sensible error response required other than ignoring writes or returning a garbage value for a read (which the current KVM MMIO API already allows). Cheers James
Re: [Qemu-devel] [PATCH v5 00/12] KVM Support for MIPS32 Processors
On 14/07/14 15:35, Peter Maydell wrote: > On 14 July 2014 14:33, James Hogan wrote: >> On 10/07/14 13:17, Peter Maydell wrote: >>> More generally, there doesn't really seem to be provision in the >>> KVM KVM_EXIT_MMIO API for returning "this access failed". >>> I guess in theory userspace could do all the "figure out how >>> to adjust CPU state to do exception entry and then run VCPU", >>> but that seems like quite a lot of work which the kernel already >>> knows how to do; is there some way to provide a simpler API >>> that lets userspace just inform the kernel that it needs to >>> fault the access? >> >> Indeed. Paolo's idea would work well I think. A data bus error exception >> would likely be the only sensible error response required other than >> ignoring writes or returning a garbage value for a read (which the >> current KVM MMIO API already allows). > > I think we should make the API at least permit returning an > (architecture-specific) error code to the kernel, rather than just > a single boolean "failed" response. For instance on ARM the > fault status registers include a single ExT bit for classifying > the type of an external abort. (The meaning of the bit is > IMPDEF; on the Cortex-A15 it can be used to distinguish > AXI bus DECERR ("decode error", ie the interconnect doesn't > have anything attached at that address) and SLVERR ("slave > error", ie there was a device at that address but it chose to > reject the transaction for some reason, eg unsupported > transfer size, timeout, write to read-only location, FIFO > overrun or just because the device was in a bad mood.) Agreed (I wasn't suggesting a bool, just thinking out loud about how mips would use that arch specific value :-) ). Cheers James
[Qemu-devel] [PATCH] target-mips: Ignore unassigned accesses with KVM
MIPS registers an unassigned access handler which raises a guest bus error exception. However this causes QEMU to crash when KVM is enabled as it isn't called from the main execution loop so longjmp() gets called without a corresponding setjmp(). Until the KVM API can be updated to trigger a guest exception in response to an MMIO exit, prevent the bus error exception being raised from mips_cpu_unassigned_access() if KVM is enabled. The check is at run time since the do_unassigned_access callback is initialised before it is known whether KVM will be enabled. The problem can be triggered with Malta emulation by making the guest write to the reset region at physical address 0x1bf0, since it is marked read-only which is treated as unassigned for writes. Signed-off-by: James Hogan Cc: Aurelien Jarno Cc: Peter Maydell Cc: Paolo Bonzini Cc: Gleb Natapov Cc: Christoffer Dall Cc: Sanjay Lal --- target-mips/op_helper.c | 11 +++ 1 file changed, 11 insertions(+) diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c index 27651a4a00c1..df97b35f8701 100644 --- a/target-mips/op_helper.c +++ b/target-mips/op_helper.c @@ -21,6 +21,7 @@ #include "qemu/host-utils.h" #include "exec/helper-proto.h" #include "exec/cpu_ldst.h" +#include "sysemu/kvm.h" #ifndef CONFIG_USER_ONLY static inline void cpu_mips_tlb_flush (CPUMIPSState *env, int flush_global); @@ -2168,6 +2169,16 @@ void mips_cpu_unassigned_access(CPUState *cs, hwaddr addr, MIPSCPU *cpu = MIPS_CPU(cs); CPUMIPSState *env = &cpu->env; +/* + * Raising an exception with KVM enabled will crash because it won't be from + * the main execution loop so the longjmp won't have a matching setjmp. + * Until we can trigger a bus error exception through KVM lets just ignore + * the access. + */ +if (kvm_enabled()) { +return; +} + if (is_exec) { helper_raise_exception(env, EXCP_IBE); } else { -- 1.8.5.5
[Qemu-devel] [PATCH] linux-user: Correct DLINFO_ITEMS
Commit a07c67dfccb1 (Implement AT_CLKTCK.) back in March 2008 added a new auxvec entry but didn't increment DLINFO_ITEMS, so it's been out of sync ever since. Bump it up to 14 so that it matches the number of NEW_AUX_ENT's that need to be counted in create_elf_tables(). Signed-off-by: James Hogan Cc: Riku Voipio Cc: Paul Brook --- linux-user/elfload.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux-user/elfload.c b/linux-user/elfload.c index 99a2c58..d2380b6 100644 --- a/linux-user/elfload.c +++ b/linux-user/elfload.c @@ -1076,7 +1076,7 @@ struct exec #define TARGET_ELF_PAGESTART(_v) ((_v) & ~(unsigned long)(TARGET_ELF_EXEC_PAGESIZE-1)) #define TARGET_ELF_PAGEOFFSET(_v) ((_v) & (TARGET_ELF_EXEC_PAGESIZE-1)) -#define DLINFO_ITEMS 13 +#define DLINFO_ITEMS 14 static inline void memcpy_fromfs(void * to, const void * from, unsigned long n) { -- 1.8.3.2
[Qemu-devel] [PATCH] linux-user: Handle arches with llseek instead of _llseek
Recently merged kernel ports (such as OpenRISC and Meta) have an llseek system call instead of _llseek. This is handled for the host architecture by defining __NR__llseek as __NR_llseek, but not for the target architecture. Handle it in the same way for these architectures, defining TARGET_NR__llseek as TARGET_NR_llseek. Signed-off-by: James Hogan Cc: Riku Voipio Cc: Jia Liu --- linux-user/syscall.c | 5 + 1 file changed, 5 insertions(+) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 2eac6d5..8dbe39b 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -198,6 +198,11 @@ static type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5, \ #define __NR__llseek __NR_lseek #endif +/* Newer kernel ports have llseek() instead of _llseek() */ +#if defined(TARGET_NR_llseek) && !defined(TARGET_NR__llseek) +#define TARGET_NR__llseek TARGET_NR_llseek +#endif + #ifdef __NR_gettid _syscall0(int, gettid) #else -- 1.8.3.2
[Qemu-devel] [PATCH] linux-user: Assert stack used for auxvec, envp, argv
Assert that the amount of stack space used for auxvec, envp & argv exactly matches the amount allocated. This catches if DLINFO_ITEMS isn't updated when another NEW_AUX_ENT is added. Signed-off-by: James Hogan Cc: Riku Voipio Cc: Peter Maydell --- This should be applied after "linux-user: Correct DLINFO_ITEMS" or the assert will fail. Tested with linux-user-test-0.3 before and after fixing DLINFO_ITEMS. --- linux-user/elfload.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/linux-user/elfload.c b/linux-user/elfload.c index d2380b6..ecf6f35 100644 --- a/linux-user/elfload.c +++ b/linux-user/elfload.c @@ -1455,6 +1455,8 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc, info->auxv_len = sp_auxv - sp; sp = loader_build_argptr(envc, argc, sp, p, 0); +/* Check the right amount of stack was allocated for auxvec, envp & argv. */ +assert(sp_auxv - sp == size); return sp; } -- 1.8.3.2
Re: [Qemu-devel] [PATCH] linux-user: Correct DLINFO_ITEMS
On Tuesday 25 March 2014 22:20:04 Peter Maydell wrote: > On 25 March 2014 21:47, James Hogan wrote: > > Commit a07c67dfccb1 (Implement AT_CLKTCK.) back in March 2008 added a > > new auxvec entry but didn't increment DLINFO_ITEMS, so it's been out of > > sync ever since. > > > > Bump it up to 14 so that it matches the number of NEW_AUX_ENT's that > > need to be counted in create_elf_tables(). > > This code could clearly use at least an assert that we've not written more > entries than we should, or ideally restructuring somehow so that we don't > have to set DLINFO_ITEMS by hand in the first place... Good idea. I've just submitted a patch to add an assert that the allocated stack for auxvec/envp/argv matches the amount used. I've already re-factored a bunch of this code to handle stacks which grow upwards (as used for HPPA and Meta arches), which would make it even more awkward to avoid DLINFO_ITEMS since it still builds the auxvec, envp and argv downwards within a new stack frame (grown upwards), so it also needs to know how much stack frame to allocate in advance to be sure it doesn't clobber other stuff lower on the stack. > Reviewed-by: Peter Maydell > for the immediate fix, though. Thanks for reviewing, Cheers James signature.asc Description: This is a digitally signed message part.
Re: [Qemu-devel] [PATCH] linux-user: Correct DLINFO_ITEMS
On Tuesday 25 March 2014 23:51:39 Peter Maydell wrote: > On 25 March 2014 23:40, James Hogan wrote: > > I've already re-factored a bunch of this code to handle stacks which grow > > upwards (as used for HPPA and Meta arches) > > ...we don't support either of those currently, do you plan to submit > something? I'm not sure yet. I have the okay to mainline our Meta QEMU fork[1], but it's fallen a little behind (v1.3.1 - and in my experiencing updating an out of tree QEMU fork is painful), so I've just been taking another look in my own time to see what it would take. Cheers James [1] https://github.com/img-meta/qemu/commit/9355e4b1929c7f05a103dc0e76fe44b54d12b2a7 signature.asc Description: This is a digitally signed message part.
Re: [Qemu-devel] [PATCH v2 10/10] target-mips: Enable KVM support in build system
Hi Peter, On 21/12/13 18:59, Peter Maydell wrote: >> @@ -4526,6 +4529,7 @@ case "$target_name" in >>\( "$target_name" = "ppc64" -a "$cpu" = "ppc" \) -o \ >>\( "$target_name" = "ppc"-a "$cpu" = "ppc64" \) -o \ >>\( "$target_name" = "ppcemb" -a "$cpu" = "ppc64" \) -o \ >> + \( "$target_name" = "mipsel" -a "$cpu" = "mips" \) -o \ >>\( "$target_name" = "x86_64" -a "$cpu" = "i386" \) -o \ >>\( "$target_name" = "i386" -a "$cpu" = "x86_64" \) \) ; then > > Really no support for mips64 or mips64el targets? At present the MIPS Linux kernel only supports KVM T&E for MIPS32r2. I would expect that to change eventually. Thanks James
Re: [Qemu-devel] [PATCH v2 09/10] hw/mips: malta: Add KVM support
On 21/12/13 20:42, Peter Maydell wrote: > On 16 December 2013 14:12, James Hogan wrote: >> +#include "linux/kvm.h" > > You can't include linux/kvm.h like this -- on Linux this will pull in > whatever the host's system kvm.h happens to be, and on non-Linux > it won't compile: > > /Users/pm215/src/qemu/hw/mips/mips_malta.c:56:10: fatal error: > 'linux/kvm.h' file not found > #include "linux/kvm.h" > ^ > 1 error generated. Thanks Peter, I've removed all these new includes except sysemu/kvm.h. Cheers James
Re: [Qemu-devel] [PATCH v2 07/10] target-mips: kvm: Add main KVM support for MIPS
Hi Andreas, On 10/02/14 14:07, Andreas Färber wrote: >> +#define dprintf(fmt, ...) \ > > dprintf is the name of a stdio.h function, so DPRINTF may be a better name. Okay. >> +int kvm_arch_init_vcpu(CPUState *env) > > Please use "env" only for CPUMIPSState, use "cpu" or "cs" here. The > usual convention is "cs" for CPUState in target-*/ so that "cpu" can be > used for MIPSCPU. Okay. >> +{ >> +dprintf("%s\n", __func__); >> +return 0; >> +} >> + >> +static inline int cpu_mips_io_interrupts_pending(CPUArchState *env) > > Please don't use CPUArchState in MIPS-specific code, use CPUMIPSState. > Although in this trivial case MIPSCPU would be more future-proof. True. >> +{ >> +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 ((cs->interrupt_request & CPU_INTERRUPT_HARD) && >> +(cpu_mips_io_interrupts_pending(env))) { > > Parentheses around cpu_mips_io_interrupts_pending() seem unnecessary > here FWIW. Good spot >> +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); > > Should this really be a printf() rather than error_report() or trace point? It looks like error_report() would indeed be better, thanks >> +int kvm_mips_set_interrupt(CPUMIPSState *env, int irq, int level) >> +{ >> +CPUState *cs = ENV_GET_CPU(env); > > CPU(mips_env_get_cpu(env)) please - ENV_GET_CPU() is for generic code > only and supposed to go away. > > Any chance a MIPSCPU *cpu (or CPUState *cs) argument can be used instead? Yep, MIPSCPU can happily be used here (I thought the same thing after fixing cpu_mips_io_interrupts_pending above). Thanks for taking the time to review! Cheers James
[Qemu-devel] [PATCH v2 00/10] KVM Support for MIPS32 Processors
This patchset implements KVM support for MIPS32 processors, using Trap & Emulation. In KVM mode, CPU virtualization is handled via the kvm kernel module, while system and I/O virtualization leverage the Malta model already present in QEMU. Both Guest kernel and Guest Userspace execute in UM. The Guest address space is as folows: Guest User address space: 0x -> 0x4000 Guest Kernel Unmapped: 0x4000 -> 0x6000 Guest Kernel Mapped:0x6000 -> 0x8000 As a result, Guest Usermode virtual memory is limited to 1GB. KVM support (by trap and emulate) was added to the Linux kernel in v3.10. This patchset is based on Sanjay Lal's V1 patchset from 2nd March 2013: https://patchwork.kernel.org/project/kvm/list/?submitter=51991&state=*&q=qemu-devel I think I've addressed all the V1 feedback. The other main change is the removal of the boot-CPS ROM code binary blob and GIC/SMP support since it's all slightly orthogonal to KVM support. Instead the existing minimal bootloader code for Malta has been updated to work with KVM T&E. A git tag for this version of the patchset can also be found on github: https://github.com/jahogan/qemu-kvm-mips.git kvm-mips-v2 Changes in v2: - Expand commit messages - Rebase on v1.7.0 - Misc checkpatch and other cleanups - Some interrupt bug fixes from Yann Le Du - Add get/set register functionality from Yann Le Du - Use new 64 bit compatible ABI from Cavium from Sanjay Lal - Add dummy kvm_arch_init_irq_routing() The common KVM code insists on calling kvm_arch_init_irq_routing() as soon as it sees kernel header support for it (regardless of whether QEMU supports it). Provide a dummy function to satisfy this. - Remove request_interrupt_window code (Peter Maydell) - Remove #ifdef CONFIG_KVM where guarded by kvm_enabled() already - Removal of cps / GIC / SMP support - Minimal bootloader modified to execute safely from RAM - Create asm-mips symlink using generic code and move above default case (Peter Maydell) - Remove redundant check of target_name = cpu = mips - Remove mipsel cross compilation fix, which is now fixed by commit 61cc919f73ea (configure: detect endian via compile test) - Add translation of guest kernel segments to allow an attached gdb to see kernel memory correctly James Hogan (3): target-mips: get_physical_address: Add defines for segment bases target-mips: get_physical_address: Add KVM awareness hw/mips: malta: Add KVM support Sanjay Lal (7): hw/mips/cputimer: Don't start periodic timer in KVM mode hw/mips: Add API to convert KVM guest KSEG0 <-> GPA kvm: Set sigmask length to 16 for MIPS targets target-mips: Set target page size to 16K in KVM mode target-mips: kvm: Add main KVM support for MIPS hw/mips: In KVM mode, inject IRQ2 (I/O) interupts via ioctls target-mips: Enable KVM support in build system configure | 6 +- hw/mips/addr.c| 10 + hw/mips/cputimer.c| 13 +- hw/mips/mips_int.c| 11 ++ hw/mips/mips_malta.c | 85 ++--- include/hw/mips/cpudevs.h | 4 + kvm-all.c | 5 + target-mips/Makefile.objs | 1 + target-mips/helper.c | 51 +++-- target-mips/kvm.c | 463 ++ target-mips/kvm_mips.h| 28 +++ target-mips/mips-defs.h | 5 + 12 files changed, 643 insertions(+), 39 deletions(-) create mode 100644 target-mips/kvm.c create mode 100644 target-mips/kvm_mips.h -- 1.8.1.2
[Qemu-devel] [PATCH v2 03/10] target-mips: get_physical_address: Add defines for segment bases
Add preprocessor definitions for 32bit segment bases for use in get_physical_address(). These will also be taken advantage of in the next patch which adds KVM awareness. Signed-off-by: James Hogan Cc: Aurelien Jarno --- target-mips/helper.c | 18 -- 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/target-mips/helper.c b/target-mips/helper.c index 33e0e88..2e96655 100644 --- a/target-mips/helper.c +++ b/target-mips/helper.c @@ -118,7 +118,13 @@ static int get_physical_address (CPUMIPSState *env, hwaddr *physical, qemu_log("user mode %d h %08x\n", user_mode, env->hflags); #endif -if (address <= (int32_t)0x7FFFUL) { +#define USEG_LIMIT 0x7FFFUL +#define KSEG0_BASE 0x8000UL +#define KSEG1_BASE 0xA000UL +#define KSEG2_BASE 0xC000UL +#define KSEG3_BASE 0xE000UL + +if (address <= USEG_LIMIT) { /* useg */ if (env->CP0_Status & (1 << CP0St_ERL)) { *physical = address & 0x; @@ -160,23 +166,23 @@ static int get_physical_address (CPUMIPSState *env, hwaddr *physical, ret = TLBRET_BADADDR; } #endif -} else if (address < (int32_t)0xA000UL) { +} else if (address < (int32_t)KSEG1_BASE) { /* kseg0 */ if (kernel_mode) { -*physical = address - (int32_t)0x8000UL; +*physical = address - (int32_t)KSEG0_BASE; *prot = PAGE_READ | PAGE_WRITE; } else { ret = TLBRET_BADADDR; } -} else if (address < (int32_t)0xC000UL) { +} else if (address < (int32_t)KSEG2_BASE) { /* kseg1 */ if (kernel_mode) { -*physical = address - (int32_t)0xA000UL; +*physical = address - (int32_t)KSEG1_BASE; *prot = PAGE_READ | PAGE_WRITE; } else { ret = TLBRET_BADADDR; } -} else if (address < (int32_t)0xE000UL) { +} else if (address < (int32_t)KSEG3_BASE) { /* sseg (kseg2) */ if (supervisor_mode || kernel_mode) { ret = env->tlb->map_address(env, physical, prot, address, rw, access_type); -- 1.8.1.2
[Qemu-devel] [PATCH v2 08/10] hw/mips: In KVM mode, inject IRQ2 (I/O) interupts via ioctls
From: Sanjay Lal COP0 emulation is in-kernel for KVM, so inject IRQ2 (I/O) interrupts via ioctls. Signed-off-by: Sanjay Lal Signed-off-by: James Hogan Cc: Aurelien Jarno --- Changes in v2: - Expand commit message - Remove #ifdef CONFIG_KVM since it's guarded by kvm_enabled() already --- hw/mips/mips_int.c | 11 +++ 1 file changed, 11 insertions(+) diff --git a/hw/mips/mips_int.c b/hw/mips/mips_int.c index 7dbd24d..1b9981e 100644 --- a/hw/mips/mips_int.c +++ b/hw/mips/mips_int.c @@ -23,6 +23,8 @@ #include "hw/hw.h" #include "hw/mips/cpudevs.h" #include "cpu.h" +#include "sysemu/kvm.h" +#include "kvm_mips.h" static void cpu_mips_irq_request(void *opaque, int irq, int level) { @@ -35,8 +37,17 @@ static void cpu_mips_irq_request(void *opaque, int irq, int level) if (level) { env->CP0_Cause |= 1 << (irq + CP0Ca_IP); + +if (kvm_enabled() && irq == 2) { +kvm_mips_set_interrupt(env, irq, level); +} + } else { env->CP0_Cause &= ~(1 << (irq + CP0Ca_IP)); + +if (kvm_enabled() && irq == 2) { +kvm_mips_set_interrupt(env, irq, level); +} } if (env->CP0_Cause & CP0Ca_IP_mask) { -- 1.8.1.2
[Qemu-devel] [PATCH v2 05/10] kvm: Set sigmask length to 16 for MIPS targets
From: Sanjay Lal MIPS/Linux is unusual in having 128 signals rather than just 64 like most other architectures. This means its sigmask is 16 bytes instead of 8, so correct kvm_set_signal_mask to pass the correct sigmask->len to KVM_SET_SIGNAL_MASK. Signed-off-by: Sanjay Lal Signed-off-by: James Hogan Cc: Gleb Natapov Cc: Paolo Bonzini --- Changes in v2: - Expand commit message - Reword comment --- kvm-all.c | 5 + 1 file changed, 5 insertions(+) diff --git a/kvm-all.c b/kvm-all.c index 4478969..c831326 100644 --- a/kvm-all.c +++ b/kvm-all.c @@ -2044,7 +2044,12 @@ int kvm_set_signal_mask(CPUState *cpu, const sigset_t *sigset) sigmask = g_malloc(sizeof(*sigmask) + sizeof(*sigset)); +#ifdef TARGET_MIPS +/* MIPS has 128 signals */ +sigmask->len = 16; +#else sigmask->len = 8; +#endif memcpy(sigmask->sigset, sigset, sizeof(*sigset)); r = kvm_vcpu_ioctl(cpu, KVM_SET_SIGNAL_MASK, sigmask); g_free(sigmask); -- 1.8.1.2
[Qemu-devel] [PATCH v2 10/10] target-mips: Enable KVM support in build system
From: Sanjay Lal Enable KVM support for MIPS in the build system. Signed-off-by: Sanjay Lal Signed-off-by: James Hogan Cc: Aurelien Jarno --- Changes in v2: - Expand commit message - Remove GIC code - Create asm-mips symlink using generic code and move above default case (Peter Maydell) - Remove redundant check of target_name = cpu = mips - Remove mipsel cross compilation fix, which is now fixed by commit 61cc919f73ea (configure: detect endian via compile test) --- configure | 6 +- target-mips/Makefile.objs | 1 + 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/configure b/configure index 0666228..7d86eea 100755 --- a/configure +++ b/configure @@ -4329,6 +4329,9 @@ if test "$linux" = "yes" ; then aarch64) linux_arch=arm64 ;; + mips64) +linux_arch=mips +;; *) # For most CPUs the kernel architecture name and QEMU CPU name match. linux_arch="$cpu" @@ -4518,7 +4521,7 @@ case "$target_name" in *) esac case "$target_name" in - arm|i386|x86_64|ppcemb|ppc|ppc64|s390x) + arm|i386|x86_64|ppcemb|ppc|ppc64|s390x|mipsel|mips) # Make sure the target and host cpus are compatible if test "$kvm" = "yes" -a "$target_softmmu" = "yes" -a \ \( "$target_name" = "$cpu" -o \ @@ -4526,6 +4529,7 @@ case "$target_name" in \( "$target_name" = "ppc64" -a "$cpu" = "ppc" \) -o \ \( "$target_name" = "ppc"-a "$cpu" = "ppc64" \) -o \ \( "$target_name" = "ppcemb" -a "$cpu" = "ppc64" \) -o \ + \( "$target_name" = "mipsel" -a "$cpu" = "mips" \) -o \ \( "$target_name" = "x86_64" -a "$cpu" = "i386" \) -o \ \( "$target_name" = "i386" -a "$cpu" = "x86_64" \) \) ; then echo "CONFIG_KVM=y" >> $config_target_mak diff --git a/target-mips/Makefile.objs b/target-mips/Makefile.objs index 0277d56..716244f 100644 --- a/target-mips/Makefile.objs +++ b/target-mips/Makefile.objs @@ -1,3 +1,4 @@ obj-y += translate.o dsp_helper.o op_helper.o lmi_helper.o helper.o cpu.o obj-y += gdbstub.o obj-$(CONFIG_SOFTMMU) += machine.o +obj-$(CONFIG_KVM) += kvm.o -- 1.8.1.2
[Qemu-devel] [PATCH v2 06/10] target-mips: Set target page size to 16K in KVM mode
From: Sanjay Lal With larger set associative caches KVM can open the possibility of cache aliasing between the memory that QEMU allocates with mmap and the mapping into the guest address space. Therefore increase the target page size to 16K when KVM is configured. Signed-off-by: Sanjay Lal Signed-off-by: James Hogan Cc: Aurelien Jarno --- Changes in v2: - Expand commit message --- target-mips/mips-defs.h | 5 + 1 file changed, 5 insertions(+) diff --git a/target-mips/mips-defs.h b/target-mips/mips-defs.h index bf094a3..473ddf8 100644 --- a/target-mips/mips-defs.h +++ b/target-mips/mips-defs.h @@ -5,7 +5,12 @@ //#define USE_HOST_FLOAT_REGS /* Real pages are variable size... */ +#ifdef CONFIG_KVM +/* For KVM/MIPS the minimum page size is 16K due to cache aliasing issues */ +#define TARGET_PAGE_BITS 14 +#else #define TARGET_PAGE_BITS 12 +#endif #define MIPS_TLB_MAX 128 #if defined(TARGET_MIPS64) -- 1.8.1.2
[Qemu-devel] [PATCH v2 09/10] hw/mips: malta: Add KVM support
In KVM mode the bootrom is loaded and executed from the last 1MB of DRAM. Based on "[PATCH 12/12] KVM/MIPS: General KVM support and support for SMP Guests" by Sanjay Lal . Signed-off-by: James Hogan Cc: Aurelien Jarno --- Changes in v2: - Removal of cps / GIC / SMP support - Minimal bootloader modified to execute safely from RAM - Remove "Writing bootloader to final 1MB of RAM" printf --- hw/mips/mips_malta.c | 85 ++-- 1 file changed, 63 insertions(+), 22 deletions(-) diff --git a/hw/mips/mips_malta.c b/hw/mips/mips_malta.c index 05c8771..3fff07c 100644 --- a/hw/mips/mips_malta.c +++ b/hw/mips/mips_malta.c @@ -51,6 +51,10 @@ #include "sysemu/qtest.h" #include "qemu/error-report.h" #include "hw/empty_slot.h" +#include "qemu/bitmap.h" +#include "sysemu/kvm.h" +#include "linux/kvm.h" +#include "kvm_mips.h" //#define DEBUG_BOARD_INIT @@ -603,29 +607,31 @@ static void network_init(PCIBus *pci_bus) */ static void write_bootloader (CPUMIPSState *env, uint8_t *base, - int64_t kernel_entry) + int64_t run_addr, int64_t kernel_entry) { uint32_t *p; /* Small bootloader */ p = (uint32_t *)base; -stl_raw(p++, 0x0bf00160); /* j 0x1fc00580 */ + +stl_raw(p++, 0x0800 | /* j 0x1fc00580 */ + ((run_addr + 0x580) & 0x0fff) >> 2); stl_raw(p++, 0x); /* nop */ /* YAMON service vector */ -stl_raw(base + 0x500, 0xbfc00580); /* start: */ -stl_raw(base + 0x504, 0xbfc0083c); /* print_count: */ -stl_raw(base + 0x520, 0xbfc00580); /* start: */ -stl_raw(base + 0x52c, 0xbfc00800); /* flush_cache: */ -stl_raw(base + 0x534, 0xbfc00808); /* print: */ -stl_raw(base + 0x538, 0xbfc00800); /* reg_cpu_isr: */ -stl_raw(base + 0x53c, 0xbfc00800); /* unred_cpu_isr: */ -stl_raw(base + 0x540, 0xbfc00800); /* reg_ic_isr: */ -stl_raw(base + 0x544, 0xbfc00800); /* unred_ic_isr: */ -stl_raw(base + 0x548, 0xbfc00800); /* reg_esr: */ -stl_raw(base + 0x54c, 0xbfc00800); /* unreg_esr: */ -stl_raw(base + 0x550, 0xbfc00800); /* getchar: */ -stl_raw(base + 0x554, 0xbfc00800); /* syscon_read: */ +stl_raw(base + 0x500, run_addr + 0x0580); /* start: */ +stl_raw(base + 0x504, run_addr + 0x083c); /* print_count: */ +stl_raw(base + 0x520, run_addr + 0x0580); /* start: */ +stl_raw(base + 0x52c, run_addr + 0x0800); /* flush_cache: */ +stl_raw(base + 0x534, run_addr + 0x0808); /* print: */ +stl_raw(base + 0x538, run_addr + 0x0800); /* reg_cpu_isr: */ +stl_raw(base + 0x53c, run_addr + 0x0800); /* unred_cpu_isr: */ +stl_raw(base + 0x540, run_addr + 0x0800); /* reg_ic_isr: */ +stl_raw(base + 0x544, run_addr + 0x0800); /* unred_ic_isr: */ +stl_raw(base + 0x548, run_addr + 0x0800); /* reg_esr: */ +stl_raw(base + 0x54c, run_addr + 0x0800); /* unreg_esr: */ +stl_raw(base + 0x550, run_addr + 0x0800); /* getchar: */ +stl_raw(base + 0x554, run_addr + 0x0800); /* syscon_read: */ /* Second part of the bootloader */ @@ -701,7 +707,7 @@ static void write_bootloader (CPUMIPSState *env, uint8_t *base, p = (uint32_t *) (base + 0x800); stl_raw(p++, 0x03e8); /* jr ra */ stl_raw(p++, 0x2402); /* li v0,0 */ - /* 808 YAMON print */ +/* 808 YAMON print */ stl_raw(p++, 0x03e06821); /* move t5,ra */ stl_raw(p++, 0x00805821); /* move t3,a0 */ stl_raw(p++, 0x00a05021); /* move t2,a1 */ @@ -774,6 +780,9 @@ static int64_t load_kernel (void) uint32_t *prom_buf; long prom_size; int prom_index = 0; +uint64_t (*xlate_to_phys) (void *opaque, uint64_t addr); +uint64_t (*xlate_to_kseg0) (void *opaque, uint64_t addr); + #ifdef TARGET_WORDS_BIGENDIAN big_endian = 1; @@ -781,7 +790,15 @@ static int64_t load_kernel (void) big_endian = 0; #endif -if (load_elf(loaderparams.kernel_filename, cpu_mips_kseg0_to_phys, NULL, +if (kvm_enabled()) { +xlate_to_phys = cpu_mips_kvm_um_kseg0_to_phys; +xlate_to_kseg0 = cpu_mips_kvm_um_phys_to_kseg0; +} else { +xlate_to_phys = cpu_mips_kseg0_to_phys; +xlate_to_kseg0 = cpu_mips_phys_to_kseg0; +} + +if (load_elf(loaderparams.kernel_filename, xlate_to_phys, NULL, (uint64_t *)&kernel_entry, NULL, (uint64_t *)&kernel_high, big_endian, ELF_MACHINE, 1) < 0) { fprintf(st
[Qemu-devel] [PATCH v2 01/10] hw/mips/cputimer: Don't start periodic timer in KVM mode
From: Sanjay Lal Compare/Count timer interrupts are handled in-kernel for KVM, so don't bother starting it in QEMU. Signed-off-by: Sanjay Lal Signed-off-by: James Hogan Cc: Aurelien Jarno --- Changes in v2: - Expand commit message - Rebase on v1.7.0 - Wrap comment --- hw/mips/cputimer.c | 13 ++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/hw/mips/cputimer.c b/hw/mips/cputimer.c index c8b4b00..52570fd 100644 --- a/hw/mips/cputimer.c +++ b/hw/mips/cputimer.c @@ -23,6 +23,7 @@ #include "hw/hw.h" #include "hw/mips/cpudevs.h" #include "qemu/timer.h" +#include "sysemu/kvm.h" #define TIMER_FREQ 100 * 1000 * 1000 @@ -141,7 +142,13 @@ static void mips_timer_cb (void *opaque) void cpu_mips_clock_init (CPUMIPSState *env) { -env->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, &mips_timer_cb, env); -env->CP0_Compare = 0; -cpu_mips_store_count(env, 1); +/* + * If we're in KVM mode, don't start the periodic timer, that is handled in + * kernel. + */ +if (!kvm_enabled()) { +env->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, &mips_timer_cb, env); +env->CP0_Compare = 0; +cpu_mips_store_count(env, 1); +} } -- 1.8.1.2
[Qemu-devel] [PATCH v2 07/10] target-mips: kvm: Add main KVM support for MIPS
From: Sanjay Lal Implement the main KVM arch API for MIPS. Signed-off-by: Sanjay Lal Signed-off-by: James Hogan Cc: Aurelien Jarno Cc: Gleb Natapov Cc: Paolo Bonzini --- Changes in v2: - Expand commit message - Checkpatch cleanups. - Some interrupt bug fixes from Yann Le Du - Add get/set register functionality from Yann Le Du - Use new 64 bit compatible ABI from Cavium from Sanjay Lal - Add dummy kvm_arch_init_irq_routing() The common KVM code insists on calling kvm_arch_init_irq_routing() as soon as it sees kernel header support for it (regardless of whether QEMU supports it). Provide a dummy function to satisfy this. - Remove request_interrupt_window code (Peter Maydell) --- target-mips/kvm.c | 463 + target-mips/kvm_mips.h | 28 +++ 2 files changed, 491 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 000..951959b --- /dev/null +++ b/target-mips/kvm.c @@ -0,0 +1,463 @@ +/* + * 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-2013 Imagination Technologies Ltd. + * 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 0 + +#define dprintf(fmt, ...) \ +do { if (DEBUG_KVM) { fprintf(stderr, fmt, ## __VA_ARGS__); } } while (0) + +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__); +} + +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; + +/* Set the registers based on QEMU's view of things */ +for (i = 0; i < 32; i++) { +regs.gpr[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; + +ret = kvm_vcpu_ioctl(cs, KVM_SET_REGS, ®s); + +if (ret < 0) { +return ret; +} + +ret = kvm_mips_te_put_cp0_registers(cs, KVM_PUT_FULL_STATE); +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.gpr[i]; +} + +env->active_tc.HI[0] = regs.hi; +env->active_tc.LO[0] = regs.lo; +env->active_tc.PC = regs.pc; + +kvm_mips_te_get_cp0_registers(cs); + +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 ((cs->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); +} +} +} + +void kvm_arch_post_run(CPUState *env, struct kvm_run *run) +{ +dprintf("%s\n", __func__); +} + +int kvm_arch_process_async_events(CPUState *cs) +{ +return cs->halted; +} + +int kvm_arch_handle_exit(
[Qemu-devel] [PATCH v2 02/10] hw/mips: Add API to convert KVM guest KSEG0 <-> GPA
From: Sanjay Lal Add APIs for converting between KVM guest KSEG0 addresses and guest physical addresses. These will be used for translating addresses when loading a kernel ELF in KVM mode. In KVM trap and emulate mode both the guest kernel and guest userspace execute in useg: Guest User address space: 0x..0x3fff Guest Kernel Unmapped: 0x4000..0x5fff Guest Kernel Mapped:0x6000..0x7fff Signed-off-by: Sanjay Lal Signed-off-by: James Hogan Cc: Aurelien Jarno --- Changes in v2: - Expand commit message - Remove unnecessary include --- hw/mips/addr.c| 10 ++ include/hw/mips/cpudevs.h | 4 2 files changed, 14 insertions(+) diff --git a/hw/mips/addr.c b/hw/mips/addr.c index 99488f1..e62d6f4 100644 --- a/hw/mips/addr.c +++ b/hw/mips/addr.c @@ -28,7 +28,17 @@ uint64_t cpu_mips_kseg0_to_phys(void *opaque, uint64_t addr) return addr & 0x7fffll; } +uint64_t cpu_mips_kvm_um_kseg0_to_phys(void *opaque, uint64_t addr) +{ +return addr & 0x3fffll; +} + uint64_t cpu_mips_phys_to_kseg0(void *opaque, uint64_t addr) { return addr | ~0x7fffll; } + +uint64_t cpu_mips_kvm_um_phys_to_kseg0(void *opaque, uint64_t addr) +{ +return addr | 0x4000ll; +} diff --git a/include/hw/mips/cpudevs.h b/include/hw/mips/cpudevs.h index 6bea24b..9e5af37 100644 --- a/include/hw/mips/cpudevs.h +++ b/include/hw/mips/cpudevs.h @@ -6,6 +6,10 @@ uint64_t cpu_mips_kseg0_to_phys(void *opaque, uint64_t addr); uint64_t cpu_mips_phys_to_kseg0(void *opaque, uint64_t addr); +uint64_t cpu_mips_kvm_um_kseg0_to_phys(void *opaque, uint64_t addr); +uint64_t cpu_mips_kvm_um_phys_to_kseg0(void *opaque, uint64_t addr); + + /* mips_int.c */ void cpu_mips_irq_init_cpu(CPUMIPSState *env); -- 1.8.1.2
[Qemu-devel] [PATCH v2 04/10] target-mips: get_physical_address: Add KVM awareness
MIPS KVM trap & emulate mode (which is currently the only supported mode) has to add an extra kseg0/kseg1 at 0x4000 and an extra kseg2/kseg3 at 0x6000. Take this into account in get_physical_address() so that debug memory access works. This is done by translating the address to a standard kseg0 or kseg2 address before doing the normal address translation. The real virtual address is still used for TLB lookups. Signed-off-by: James Hogan Cc: Aurelien Jarno --- target-mips/helper.c | 33 ++--- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/target-mips/helper.c b/target-mips/helper.c index 2e96655..c4be887 100644 --- a/target-mips/helper.c +++ b/target-mips/helper.c @@ -24,6 +24,7 @@ #include #include "cpu.h" +#include "sysemu/kvm.h" enum { TLBRET_DIRTY = -4, @@ -100,7 +101,7 @@ int r4k_map_address (CPUMIPSState *env, hwaddr *physical, int *prot, } static int get_physical_address (CPUMIPSState *env, hwaddr *physical, -int *prot, target_ulong address, +int *prot, target_ulong real_address, int rw, int access_type) { /* User mode can only access useg/xuseg */ @@ -113,6 +114,8 @@ static int get_physical_address (CPUMIPSState *env, hwaddr *physical, int KX = (env->CP0_Status & (1 << CP0St_KX)) != 0; #endif int ret = TLBRET_MATCH; +/* effective address (modified for KVM T&E kernel segments) */ +target_ulong address = real_address; #if 0 qemu_log("user mode %d h %08x\n", user_mode, env->hflags); @@ -124,19 +127,35 @@ static int get_physical_address (CPUMIPSState *env, hwaddr *physical, #define KSEG2_BASE 0xC000UL #define KSEG3_BASE 0xE000UL +#define KVM_KSEG0_BASE 0x4000UL +#define KVM_KSEG2_BASE 0x6000UL + +if (kvm_enabled()) { +/* KVM T&E adds guest kernel segments in useg */ +if (real_address >= KVM_KSEG0_BASE) { +if (real_address < KVM_KSEG2_BASE) { +/* kseg0 */ +address += KSEG0_BASE - KVM_KSEG0_BASE; +} else if (real_address <= USEG_LIMIT) { +/* kseg2/3 */ +address += KSEG2_BASE - KVM_KSEG2_BASE; +} +} +} + if (address <= USEG_LIMIT) { /* useg */ if (env->CP0_Status & (1 << CP0St_ERL)) { *physical = address & 0x; *prot = PAGE_READ | PAGE_WRITE; } else { -ret = env->tlb->map_address(env, physical, prot, address, rw, access_type); +ret = env->tlb->map_address(env, physical, prot, real_address, rw, access_type); } #if defined(TARGET_MIPS64) } else if (address < 0x4000ULL) { /* xuseg */ if (UX && address <= (0x3FFFULL & env->SEGMask)) { -ret = env->tlb->map_address(env, physical, prot, address, rw, access_type); +ret = env->tlb->map_address(env, physical, prot, real_address, rw, access_type); } else { ret = TLBRET_BADADDR; } @@ -144,7 +163,7 @@ static int get_physical_address (CPUMIPSState *env, hwaddr *physical, /* xsseg */ if ((supervisor_mode || kernel_mode) && SX && address <= (0x7FFFULL & env->SEGMask)) { -ret = env->tlb->map_address(env, physical, prot, address, rw, access_type); +ret = env->tlb->map_address(env, physical, prot, real_address, rw, access_type); } else { ret = TLBRET_BADADDR; } @@ -161,7 +180,7 @@ static int get_physical_address (CPUMIPSState *env, hwaddr *physical, /* xkseg */ if (kernel_mode && KX && address <= (0x7FFFULL & env->SEGMask)) { -ret = env->tlb->map_address(env, physical, prot, address, rw, access_type); +ret = env->tlb->map_address(env, physical, prot, real_address, rw, access_type); } else { ret = TLBRET_BADADDR; } @@ -185,7 +204,7 @@ static int get_physical_address (CPUMIPSState *env, hwaddr *physical, } else if (address < (int32_t)KSEG3_BASE) { /* sseg (kseg2) */ if (supervisor_mode || kernel_mode) { -ret = env->tlb->map_address(env, physical, prot, address, rw, access_type); +ret = env->tlb->map_address(env, physical, prot, real_address, rw, access_type); } else { ret = TLBRET_BADADDR; } @@ -193,7 +212,7 @@ static int get_physical_address (CPUMIPSState *env, hwaddr *physical, /* kseg3 */ /* XXX: debug segment is not emulated */ if (kernel_mode) { -ret = env->tlb->map_address(env, physical, prot, address, rw, access_type); +ret = env->tlb->map_address(env, physical, prot, real_address, rw, access_type); } else { ret = TLBRET_BADADDR; } -- 1.8.1.2
Re: [Qemu-devel] Does QEMU support MIPS SMP2 malta board?
Hi Nancy, On 15/11/13 09:48, Nancy wrote: > I notes the smp based on kvm implement, but there do not have kvm > implement under target-mips? how this smp implement? Is there any > document record the QEMU MIPS smp internal? The KVM patchset added a binary blob of the CPS bootloader to support multicore: https://patchwork.kernel.org/patch/2207161/ I believe it's related to the fact that on most real hardware the reset vectors of the cores aren't controllable so they all start in the boot PROM, therefore you need some code there to put the other cores in a loop waiting to be told to go somewhere by the OS. Cheers James
[Qemu-devel] [PATCH v3 7/9] hw/mips: In KVM mode, inject IRQ2 (I/O) interupts via ioctls
From: Sanjay Lal COP0 emulation is in-kernel for KVM, so inject IRQ2 (I/O) interrupts via ioctls. Signed-off-by: Sanjay Lal Signed-off-by: James Hogan Reviewed-by: Aurelien Jarno Cc: Andreas Färber --- Changes in v3: - Pass MIPSCPU to kvm_mips_set_[ipi_]interrupt (Andreas Färber). Changes in v2: - Expand commit message - Remove #ifdef CONFIG_KVM since it's guarded by kvm_enabled() already --- hw/mips/mips_int.c | 11 +++ 1 file changed, 11 insertions(+) diff --git a/hw/mips/mips_int.c b/hw/mips/mips_int.c index 7dbd24d..d740046 100644 --- a/hw/mips/mips_int.c +++ b/hw/mips/mips_int.c @@ -23,6 +23,8 @@ #include "hw/hw.h" #include "hw/mips/cpudevs.h" #include "cpu.h" +#include "sysemu/kvm.h" +#include "kvm_mips.h" static void cpu_mips_irq_request(void *opaque, int irq, int level) { @@ -35,8 +37,17 @@ static void cpu_mips_irq_request(void *opaque, int irq, int level) if (level) { env->CP0_Cause |= 1 << (irq + CP0Ca_IP); + +if (kvm_enabled() && irq == 2) { +kvm_mips_set_interrupt(cpu, irq, level); +} + } else { env->CP0_Cause &= ~(1 << (irq + CP0Ca_IP)); + +if (kvm_enabled() && irq == 2) { +kvm_mips_set_interrupt(cpu, irq, level); +} } if (env->CP0_Cause & CP0Ca_IP_mask) { -- 1.8.1.2
[Qemu-devel] [PATCH v3 3/9] target-mips: get_physical_address: Add defines for segment bases
Add preprocessor definitions for 32bit segment bases for use in get_physical_address(). These will also be taken advantage of in the next patch which adds KVM awareness. Signed-off-by: James Hogan Reviewed-by: Aurelien Jarno --- target-mips/helper.c | 18 -- 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/target-mips/helper.c b/target-mips/helper.c index 33e0e88..2e96655 100644 --- a/target-mips/helper.c +++ b/target-mips/helper.c @@ -118,7 +118,13 @@ static int get_physical_address (CPUMIPSState *env, hwaddr *physical, qemu_log("user mode %d h %08x\n", user_mode, env->hflags); #endif -if (address <= (int32_t)0x7FFFUL) { +#define USEG_LIMIT 0x7FFFUL +#define KSEG0_BASE 0x8000UL +#define KSEG1_BASE 0xA000UL +#define KSEG2_BASE 0xC000UL +#define KSEG3_BASE 0xE000UL + +if (address <= USEG_LIMIT) { /* useg */ if (env->CP0_Status & (1 << CP0St_ERL)) { *physical = address & 0x; @@ -160,23 +166,23 @@ static int get_physical_address (CPUMIPSState *env, hwaddr *physical, ret = TLBRET_BADADDR; } #endif -} else if (address < (int32_t)0xA000UL) { +} else if (address < (int32_t)KSEG1_BASE) { /* kseg0 */ if (kernel_mode) { -*physical = address - (int32_t)0x8000UL; +*physical = address - (int32_t)KSEG0_BASE; *prot = PAGE_READ | PAGE_WRITE; } else { ret = TLBRET_BADADDR; } -} else if (address < (int32_t)0xC000UL) { +} else if (address < (int32_t)KSEG2_BASE) { /* kseg1 */ if (kernel_mode) { -*physical = address - (int32_t)0xA000UL; +*physical = address - (int32_t)KSEG1_BASE; *prot = PAGE_READ | PAGE_WRITE; } else { ret = TLBRET_BADADDR; } -} else if (address < (int32_t)0xE000UL) { +} else if (address < (int32_t)KSEG3_BASE) { /* sseg (kseg2) */ if (supervisor_mode || kernel_mode) { ret = env->tlb->map_address(env, physical, prot, address, rw, access_type); -- 1.8.1.2
[Qemu-devel] [PATCH v3 1/9] hw/mips/cputimer: Don't start periodic timer in KVM mode
From: Sanjay Lal Compare/Count timer interrupts are handled in-kernel for KVM, so don't bother starting it in QEMU. Signed-off-by: Sanjay Lal Signed-off-by: James Hogan Reviewed-by: Aurelien Jarno --- Changes in v2: - Expand commit message - Rebase on v1.7.0 - Wrap comment --- hw/mips/cputimer.c | 13 ++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/hw/mips/cputimer.c b/hw/mips/cputimer.c index c8b4b00..52570fd 100644 --- a/hw/mips/cputimer.c +++ b/hw/mips/cputimer.c @@ -23,6 +23,7 @@ #include "hw/hw.h" #include "hw/mips/cpudevs.h" #include "qemu/timer.h" +#include "sysemu/kvm.h" #define TIMER_FREQ 100 * 1000 * 1000 @@ -141,7 +142,13 @@ static void mips_timer_cb (void *opaque) void cpu_mips_clock_init (CPUMIPSState *env) { -env->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, &mips_timer_cb, env); -env->CP0_Compare = 0; -cpu_mips_store_count(env, 1); +/* + * If we're in KVM mode, don't start the periodic timer, that is handled in + * kernel. + */ +if (!kvm_enabled()) { +env->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, &mips_timer_cb, env); +env->CP0_Compare = 0; +cpu_mips_store_count(env, 1); +} } -- 1.8.1.2
[Qemu-devel] [PATCH v3 2/9] hw/mips: Add API to convert KVM guest KSEG0 <-> GPA
From: Sanjay Lal Add APIs for converting between KVM guest KSEG0 addresses and guest physical addresses. These will be used for translating addresses when loading a kernel ELF in KVM mode. In KVM trap and emulate mode both the guest kernel and guest userspace execute in useg: Guest User address space: 0x..0x3fff Guest Kernel Unmapped: 0x4000..0x5fff Guest Kernel Mapped:0x6000..0x7fff Signed-off-by: Sanjay Lal Signed-off-by: James Hogan Reviewed-by: Aurelien Jarno --- Changes in v2: - Expand commit message - Remove unnecessary include --- hw/mips/addr.c| 10 ++ include/hw/mips/cpudevs.h | 4 2 files changed, 14 insertions(+) diff --git a/hw/mips/addr.c b/hw/mips/addr.c index 99488f1..e62d6f4 100644 --- a/hw/mips/addr.c +++ b/hw/mips/addr.c @@ -28,7 +28,17 @@ uint64_t cpu_mips_kseg0_to_phys(void *opaque, uint64_t addr) return addr & 0x7fffll; } +uint64_t cpu_mips_kvm_um_kseg0_to_phys(void *opaque, uint64_t addr) +{ +return addr & 0x3fffll; +} + uint64_t cpu_mips_phys_to_kseg0(void *opaque, uint64_t addr) { return addr | ~0x7fffll; } + +uint64_t cpu_mips_kvm_um_phys_to_kseg0(void *opaque, uint64_t addr) +{ +return addr | 0x4000ll; +} diff --git a/include/hw/mips/cpudevs.h b/include/hw/mips/cpudevs.h index 6bea24b..9e5af37 100644 --- a/include/hw/mips/cpudevs.h +++ b/include/hw/mips/cpudevs.h @@ -6,6 +6,10 @@ uint64_t cpu_mips_kseg0_to_phys(void *opaque, uint64_t addr); uint64_t cpu_mips_phys_to_kseg0(void *opaque, uint64_t addr); +uint64_t cpu_mips_kvm_um_kseg0_to_phys(void *opaque, uint64_t addr); +uint64_t cpu_mips_kvm_um_phys_to_kseg0(void *opaque, uint64_t addr); + + /* mips_int.c */ void cpu_mips_irq_init_cpu(CPUMIPSState *env); -- 1.8.1.2
[Qemu-devel] [PATCH v3 6/9] target-mips: kvm: Add main KVM support for MIPS
From: Sanjay Lal Implement the main KVM arch API for MIPS. Signed-off-by: Sanjay Lal Signed-off-by: James Hogan Cc: Aurelien Jarno Cc: Gleb Natapov Cc: Paolo Bonzini Cc: Andreas Färber Cc: Peter Maydell --- Changes in v3: - s/dprintf/DPRINTF/ (Andreas Färber). - Use "cs" rather than "cpu" or "env" for CPUState variable names (Andreas Färber). - Use CPUMIPSState rather than CPUArchState (Andreas Färber). - Pass MIPSCPU to cpu_mips_io_interrupts_pending() rather than CPUMIPSState (Andreas Färber). - Remove spurious parentheses around cpu_mips_io_interrupts_pending() call (Andreas Färber). - Pass MIPSCPU to kvm_mips_set_[ipi_]interrupt (Andreas Färber). - Make use of error_report (Andreas Färber) and clean up error messages a little to include __func__. - Remove inline kvm_mips_{put,get}_one_[ul]reg() declarations from kvm_mips.h. They're only used in target-mips/kvm.c anyway. - Make kvm_arch_{put,get}_registers static within target-mips/kvm.c and remove from kvm_mips.h. - Set sigmask length to 16 from kvm_arch_init() since MIPS Linux has 128 signals. This is better than cluttering kvm_all.c with TARGET_* ifdefs (Peter Maydell). Changes in v2: - Expand commit message - Checkpatch cleanups. - Some interrupt bug fixes from Yann Le Du - Add get/set register functionality from Yann Le Du - Use new 64 bit compatible ABI from Cavium from Sanjay Lal - Add dummy kvm_arch_init_irq_routing() The common KVM code insists on calling kvm_arch_init_irq_routing() as soon as it sees kernel header support for it (regardless of whether QEMU supports it). Provide a dummy function to satisfy this. - Remove request_interrupt_window code (Peter Maydell) --- target-mips/kvm.c | 472 + target-mips/kvm_mips.h | 19 ++ 2 files changed, 491 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 000..0ec343d --- /dev/null +++ b/target-mips/kvm.c @@ -0,0 +1,472 @@ +/* + * 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-2014 Imagination Technologies Ltd. + * Authors: Sanjay Lal +*/ + +#include +#include +#include + +#include + +#include "qemu-common.h" +#include "qemu/error-report.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 0 + +#define DPRINTF(fmt, ...) \ +do { if (DEBUG_KVM) { fprintf(stderr, fmt, ## __VA_ARGS__); } } while (0) + +const KVMCapabilityInfo kvm_arch_required_capabilities[] = { +KVM_CAP_LAST_INFO +}; + +unsigned long kvm_arch_vcpu_id(CPUState *cs) +{ +return cs->cpu_index; +} + +int kvm_arch_init(KVMState *s) +{ +/* MIPS has 128 signals */ +kvm_set_sigmask_len(s, 16); + +DPRINTF("%s\n", __func__); +return 0; +} + +int kvm_arch_init_vcpu(CPUState *cs) +{ +int ret = 0; +DPRINTF("%s\n", __func__); +return ret; +} + +void kvm_arch_reset_vcpu(CPUState *cs) +{ +DPRINTF("%s\n", __func__); +} + +int kvm_arch_insert_sw_breakpoint(CPUState *cs, struct kvm_sw_breakpoint *bp) +{ +DPRINTF("%s\n", __func__); +return 0; +} + +int kvm_arch_remove_sw_breakpoint(CPUState *cs, struct kvm_sw_breakpoint *bp) +{ +DPRINTF("%s\n", __func__); +return 0; +} + +static inline int cpu_mips_io_interrupts_pending(MIPSCPU *cpu) +{ +CPUMIPSState *env = &cpu->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); +int r; +struct kvm_mips_interrupt intr; + +if ((cs->interrupt_request & CPU_INTERRUPT_HARD) && +cpu_mips_io_interrupts_pending(cpu)) { +intr.cpu = -1; +intr.irq = 2; +r = kvm_vcpu_ioctl(cs, KVM_INTERRUPT, &intr); +if (r < 0) { +error_report("%s: cpu %d: failed to inject IRQ %x", + __func__, cs->cpu_index, intr.irq); +} +} +} + +void kvm_arch_post_run(CPUState *cs, struct kvm_run *run) +{ +DPRINTF("%s\n", __func__); +} + +int kvm_arch_process_async_events(CPUState *cs) +{ +return cs->halted; +} + +int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run) +{ +int ret; + +DPRINTF("%s\n", __func__); +switch (run->exit_reason) { +default: +
[Qemu-devel] [PATCH v3 9/9] target-mips: Enable KVM support in build system
From: Sanjay Lal Enable KVM support for MIPS in the build system. Signed-off-by: Sanjay Lal Signed-off-by: James Hogan Reviewed-by: Aurelien Jarno --- Changes in v2: - Expand commit message - Remove GIC code - Create asm-mips symlink using generic code and move above default case (Peter Maydell) - Remove redundant check of target_name = cpu = mips - Remove mipsel cross compilation fix, which is now fixed by commit 61cc919f73ea (configure: detect endian via compile test) --- configure | 6 +- target-mips/Makefile.objs | 1 + 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/configure b/configure index 6ccadc3..f9e38d3 100755 --- a/configure +++ b/configure @@ -4675,6 +4675,9 @@ if test "$linux" = "yes" ; then aarch64) linux_arch=arm64 ;; + mips64) +linux_arch=mips +;; *) # For most CPUs the kernel architecture name and QEMU CPU name match. linux_arch="$cpu" @@ -4864,7 +4867,7 @@ case "$target_name" in *) esac case "$target_name" in - aarch64|arm|i386|x86_64|ppcemb|ppc|ppc64|s390x) + aarch64|arm|i386|x86_64|ppcemb|ppc|ppc64|s390x|mipsel|mips) # Make sure the target and host cpus are compatible if test "$kvm" = "yes" -a "$target_softmmu" = "yes" -a \ \( "$target_name" = "$cpu" -o \ @@ -4872,6 +4875,7 @@ case "$target_name" in \( "$target_name" = "ppc64" -a "$cpu" = "ppc" \) -o \ \( "$target_name" = "ppc"-a "$cpu" = "ppc64" \) -o \ \( "$target_name" = "ppcemb" -a "$cpu" = "ppc64" \) -o \ + \( "$target_name" = "mipsel" -a "$cpu" = "mips" \) -o \ \( "$target_name" = "x86_64" -a "$cpu" = "i386" \) -o \ \( "$target_name" = "i386" -a "$cpu" = "x86_64" \) \) ; then echo "CONFIG_KVM=y" >> $config_target_mak diff --git a/target-mips/Makefile.objs b/target-mips/Makefile.objs index 0277d56..716244f 100644 --- a/target-mips/Makefile.objs +++ b/target-mips/Makefile.objs @@ -1,3 +1,4 @@ obj-y += translate.o dsp_helper.o op_helper.o lmi_helper.o helper.o cpu.o obj-y += gdbstub.o obj-$(CONFIG_SOFTMMU) += machine.o +obj-$(CONFIG_KVM) += kvm.o -- 1.8.1.2
[Qemu-devel] [PATCH v3 0/9] KVM Support for MIPS32 Processors
This patchset implements KVM support for MIPS32 processors, using Trap & Emulation. In KVM mode, CPU virtualization is handled via the kvm kernel module, while system and I/O virtualization leverage the Malta model already present in QEMU. Both Guest kernel and Guest Userspace execute in UM. The Guest address space is as folows: Guest User address space: 0x -> 0x4000 Guest Kernel Unmapped: 0x4000 -> 0x6000 Guest Kernel Mapped:0x6000 -> 0x8000 As a result, Guest Usermode virtual memory is limited to 1GB. KVM support (by trap and emulate) was added to the Linux kernel in v3.10. Changes in v3: Changes mostly addressing review comments from v2 patchset. A git tag for this version of the patchset can also be found on github: https://github.com/jahogan/qemu-kvm-mips.git kvm-mips-v3 - Remove "target-mips: Set target page size to 16K in KVM mode". It should actually work fine with 4k TARGET_PAGE_SIZE as long as there is no cache aliasing or both host and guest kernels are configured to a sufficient page size to avoid aliasing (which the kernel arch/mips/kvm/00README.txt alludes to anyway). - Rewrote kvm sigmask patch to allow sigmask length to be set by kvm_arch_init(), so that MIPS can set it to 16 as it has 128 signals. This is better than cluttering kvm-all.c with TARGET_* ifdefs (Peter Maydell). - Set sigmask length to 16 from kvm_arch_init() since MIPS Linux has 128 signals. This is better than cluttering kvm_all.c with TARGET_* ifdefs (Peter Maydell). - s/dprintf/DPRINTF/ (Andreas Färber). - Use "cs" rather than "cpu" or "env" for CPUState variable names (Andreas Färber). - Use CPUMIPSState rather than CPUArchState (Andreas Färber). - Pass MIPSCPU to cpu_mips_io_interrupts_pending() rather than CPUMIPSState (Andreas Färber). - Remove spurious parentheses around cpu_mips_io_interrupts_pending() call (Andreas Färber). - Pass MIPSCPU to kvm_mips_set_[ipi_]interrupt (Andreas Färber). - Make use of error_report (Andreas Färber) and clean up error messages a little to include __func__. - Remove inline kvm_mips_{put,get}_one_[ul]reg() declarations from kvm_mips.h. They're only used in target-mips/kvm.c anyway. - Make kvm_arch_{put,get}_registers static within target-mips/kvm.c and remove from kvm_mips.h. - Remove unnecessary includes from Malta patch, especially linux/kvm.h which isn't a good idea on non-Linux (Peter Maydell). Changes in v2: This patchset is based on Sanjay Lal's V1 patchset from 2nd March 2013: https://patchwork.kernel.org/project/kvm/list/?submitter=51991&state=*&q=qemu-devel I think I've addressed all the V1 feedback. The other main change is the removal of the boot-CPS ROM code binary blob and GIC/SMP support since it's all slightly orthogonal to KVM support. Instead the existing minimal bootloader code for Malta has been updated to work with KVM T&E. A git tag for this version of the patchset can also be found on github: https://github.com/jahogan/qemu-kvm-mips.git kvm-mips-v2 - Expand commit messages - Rebase on v1.7.0 - Misc checkpatch and other cleanups - Some interrupt bug fixes from Yann Le Du - Add get/set register functionality from Yann Le Du - Use new 64 bit compatible ABI from Cavium from Sanjay Lal - Add dummy kvm_arch_init_irq_routing() The common KVM code insists on calling kvm_arch_init_irq_routing() as soon as it sees kernel header support for it (regardless of whether QEMU supports it). Provide a dummy function to satisfy this. - Remove request_interrupt_window code (Peter Maydell) - Remove #ifdef CONFIG_KVM where guarded by kvm_enabled() already - Removal of cps / GIC / SMP support - Minimal bootloader modified to execute safely from RAM - Create asm-mips symlink using generic code and move above default case (Peter Maydell) - Remove redundant check of target_name = cpu = mips - Remove mipsel cross compilation fix, which is now fixed by commit 61cc919f73ea (configure: detect endian via compile test) - Add translation of guest kernel segments to allow an attached gdb to see kernel memory correctly James Hogan (4): target-mips: get_physical_address: Add defines for segment bases target-mips: get_physical_address: Add KVM awareness kvm: Allow arch to set sigmask length hw/mips: malta: Add KVM support Sanjay Lal (5): hw/mips/cputimer: Don't start periodic timer in KVM mode hw/mips: Add API to convert KVM guest KSEG0 <-> GPA target-mips: kvm: Add main KVM support for MIPS hw/mips: In KVM mode, inject IRQ2 (I/O) interupts via ioctls target-mips: Enable KVM support in build system configure | 6 +- hw/mips/addr.c| 10 + hw/mips/cputimer.c| 13 +- hw/mips/mips_int.c| 11 ++ hw/mips/mips_malta.c | 82 +--- include/hw/mips/cpudevs.h | 4 + include/sys
[Qemu-devel] [PATCH v3 4/9] target-mips: get_physical_address: Add KVM awareness
MIPS KVM trap & emulate mode (which is currently the only supported mode) has to add an extra kseg0/kseg1 at 0x4000 and an extra kseg2/kseg3 at 0x6000. Take this into account in get_physical_address() so that debug memory access works. This is done by translating the address to a standard kseg0 or kseg2 address before doing the normal address translation. The real virtual address is still used for TLB lookups. Signed-off-by: James Hogan Cc: Aurelien Jarno --- target-mips/helper.c | 33 ++--- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/target-mips/helper.c b/target-mips/helper.c index 2e96655..c4be887 100644 --- a/target-mips/helper.c +++ b/target-mips/helper.c @@ -24,6 +24,7 @@ #include #include "cpu.h" +#include "sysemu/kvm.h" enum { TLBRET_DIRTY = -4, @@ -100,7 +101,7 @@ int r4k_map_address (CPUMIPSState *env, hwaddr *physical, int *prot, } static int get_physical_address (CPUMIPSState *env, hwaddr *physical, -int *prot, target_ulong address, +int *prot, target_ulong real_address, int rw, int access_type) { /* User mode can only access useg/xuseg */ @@ -113,6 +114,8 @@ static int get_physical_address (CPUMIPSState *env, hwaddr *physical, int KX = (env->CP0_Status & (1 << CP0St_KX)) != 0; #endif int ret = TLBRET_MATCH; +/* effective address (modified for KVM T&E kernel segments) */ +target_ulong address = real_address; #if 0 qemu_log("user mode %d h %08x\n", user_mode, env->hflags); @@ -124,19 +127,35 @@ static int get_physical_address (CPUMIPSState *env, hwaddr *physical, #define KSEG2_BASE 0xC000UL #define KSEG3_BASE 0xE000UL +#define KVM_KSEG0_BASE 0x4000UL +#define KVM_KSEG2_BASE 0x6000UL + +if (kvm_enabled()) { +/* KVM T&E adds guest kernel segments in useg */ +if (real_address >= KVM_KSEG0_BASE) { +if (real_address < KVM_KSEG2_BASE) { +/* kseg0 */ +address += KSEG0_BASE - KVM_KSEG0_BASE; +} else if (real_address <= USEG_LIMIT) { +/* kseg2/3 */ +address += KSEG2_BASE - KVM_KSEG2_BASE; +} +} +} + if (address <= USEG_LIMIT) { /* useg */ if (env->CP0_Status & (1 << CP0St_ERL)) { *physical = address & 0x; *prot = PAGE_READ | PAGE_WRITE; } else { -ret = env->tlb->map_address(env, physical, prot, address, rw, access_type); +ret = env->tlb->map_address(env, physical, prot, real_address, rw, access_type); } #if defined(TARGET_MIPS64) } else if (address < 0x4000ULL) { /* xuseg */ if (UX && address <= (0x3FFFULL & env->SEGMask)) { -ret = env->tlb->map_address(env, physical, prot, address, rw, access_type); +ret = env->tlb->map_address(env, physical, prot, real_address, rw, access_type); } else { ret = TLBRET_BADADDR; } @@ -144,7 +163,7 @@ static int get_physical_address (CPUMIPSState *env, hwaddr *physical, /* xsseg */ if ((supervisor_mode || kernel_mode) && SX && address <= (0x7FFFULL & env->SEGMask)) { -ret = env->tlb->map_address(env, physical, prot, address, rw, access_type); +ret = env->tlb->map_address(env, physical, prot, real_address, rw, access_type); } else { ret = TLBRET_BADADDR; } @@ -161,7 +180,7 @@ static int get_physical_address (CPUMIPSState *env, hwaddr *physical, /* xkseg */ if (kernel_mode && KX && address <= (0x7FFFULL & env->SEGMask)) { -ret = env->tlb->map_address(env, physical, prot, address, rw, access_type); +ret = env->tlb->map_address(env, physical, prot, real_address, rw, access_type); } else { ret = TLBRET_BADADDR; } @@ -185,7 +204,7 @@ static int get_physical_address (CPUMIPSState *env, hwaddr *physical, } else if (address < (int32_t)KSEG3_BASE) { /* sseg (kseg2) */ if (supervisor_mode || kernel_mode) { -ret = env->tlb->map_address(env, physical, prot, address, rw, access_type); +ret = env->tlb->map_address(env, physical, prot, real_address, rw, access_type); } else { ret = TLBRET_BADADDR; } @@ -193,7 +212,7 @@ static int get_physical_address (CPUMIPSState *env, hwaddr *physical, /* kseg3 */ /* XXX: debug segment is not emulated */ if (kernel_mode) { -ret = env->tlb->map_address(env, physical, prot, address, rw, access_type); +ret = env->tlb->map_address(env, physical, prot, real_address, rw, access_type); } else { ret = TLBRET_BADADDR; } -- 1.8.1.2
[Qemu-devel] [PATCH v3 5/9] kvm: Allow arch to set sigmask length
MIPS/Linux is unusual in having 128 signals rather than just 64 like most other architectures. This means its sigmask is 16 bytes instead of 8, so allow arches to override the sigmask->len value passed to the KVM_SET_SIGNAL_MASK ioctl in kvm_set_signal_mask() by calling kvm_set_sigmask_len() from kvm_arch_init(). Otherwise default to 8 bytes. Signed-off-by: James Hogan Cc: Aurelien Jarno Cc: Sanjay Lal Cc: Gleb Natapov Cc: Paolo Bonzini Cc: Peter Maydell --- Changes in v3: - Rewrote to allow sigmask length to be set by kvm_arch_init(), so that MIPS can set it to 16 as it has 128 signals. This is better than cluttering kvm-all.c with TARGET_* ifdefs (Peter Maydell). Changes in v2: - Expand commit message - Reword comment --- include/sysemu/kvm.h | 2 ++ kvm-all.c| 11 ++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h index a02d67c..e037f69 100644 --- a/include/sysemu/kvm.h +++ b/include/sysemu/kvm.h @@ -297,6 +297,8 @@ int kvm_check_extension(KVMState *s, unsigned int extension); uint32_t kvm_arch_get_supported_cpuid(KVMState *env, uint32_t function, uint32_t index, int reg); +void kvm_set_sigmask_len(KVMState *s, unsigned int sigmask_len); + #if !defined(CONFIG_USER_ONLY) int kvm_physical_memory_addr_from_host(KVMState *s, void *ram_addr, hwaddr *phys_addr); diff --git a/kvm-all.c b/kvm-all.c index fd8157a..efcf252 100644 --- a/kvm-all.c +++ b/kvm-all.c @@ -96,6 +96,7 @@ struct KVMState * they're not. Linux, glibc and *BSD all treat ioctl numbers as * unsigned, and treating them as signed here can break things */ unsigned irq_set_ioctl; +unsigned int sigmask_len; #ifdef KVM_CAP_IRQ_ROUTING struct kvm_irq_routing *irq_routes; int nr_allocated_irq_routes; @@ -1369,6 +1370,8 @@ int kvm_init(void) assert(TARGET_PAGE_SIZE <= getpagesize()); page_size_init(); +s->sigmask_len = 8; + #ifdef KVM_CAP_SET_GUEST_DEBUG QTAILQ_INIT(&s->kvm_sw_breakpoints); #endif @@ -1538,6 +1541,11 @@ err: return ret; } +void kvm_set_sigmask_len(KVMState *s, unsigned int sigmask_len) +{ +s->sigmask_len = sigmask_len; +} + static void kvm_handle_io(uint16_t port, void *data, int direction, int size, uint32_t count) { @@ -2058,6 +2066,7 @@ void kvm_remove_all_breakpoints(CPUState *cpu) int kvm_set_signal_mask(CPUState *cpu, const sigset_t *sigset) { +KVMState *s = kvm_state; struct kvm_signal_mask *sigmask; int r; @@ -2067,7 +2076,7 @@ int kvm_set_signal_mask(CPUState *cpu, const sigset_t *sigset) sigmask = g_malloc(sizeof(*sigmask) + sizeof(*sigset)); -sigmask->len = 8; +sigmask->len = s->sigmask_len; memcpy(sigmask->sigset, sigset, sizeof(*sigset)); r = kvm_vcpu_ioctl(cpu, KVM_SET_SIGNAL_MASK, sigmask); g_free(sigmask); -- 1.8.1.2
[Qemu-devel] [PATCH v3 8/9] hw/mips: malta: Add KVM support
In KVM mode the bootrom is loaded and executed from the last 1MB of DRAM. Based on "[PATCH 12/12] KVM/MIPS: General KVM support and support for SMP Guests" by Sanjay Lal . Signed-off-by: James Hogan Reviewed-by: Aurelien Jarno Cc: Peter Maydell Cc: Sanjay Lal --- Changes in v3: - Remove unnecessary includes, especially linux/kvm.h which isn't a good idea on non-Linux (Peter Maydell). Changes in v2: - Removal of cps / GIC / SMP support - Minimal bootloader modified to execute safely from RAM - Remove "Writing bootloader to final 1MB of RAM" printf --- hw/mips/mips_malta.c | 82 ++-- 1 file changed, 60 insertions(+), 22 deletions(-) diff --git a/hw/mips/mips_malta.c b/hw/mips/mips_malta.c index ac5ec44..90b20d6 100644 --- a/hw/mips/mips_malta.c +++ b/hw/mips/mips_malta.c @@ -51,6 +51,7 @@ #include "sysemu/qtest.h" #include "qemu/error-report.h" #include "hw/empty_slot.h" +#include "sysemu/kvm.h" //#define DEBUG_BOARD_INIT @@ -603,29 +604,31 @@ static void network_init(PCIBus *pci_bus) */ static void write_bootloader (CPUMIPSState *env, uint8_t *base, - int64_t kernel_entry) + int64_t run_addr, int64_t kernel_entry) { uint32_t *p; /* Small bootloader */ p = (uint32_t *)base; -stl_raw(p++, 0x0bf00160); /* j 0x1fc00580 */ + +stl_raw(p++, 0x0800 | /* j 0x1fc00580 */ + ((run_addr + 0x580) & 0x0fff) >> 2); stl_raw(p++, 0x); /* nop */ /* YAMON service vector */ -stl_raw(base + 0x500, 0xbfc00580); /* start: */ -stl_raw(base + 0x504, 0xbfc0083c); /* print_count: */ -stl_raw(base + 0x520, 0xbfc00580); /* start: */ -stl_raw(base + 0x52c, 0xbfc00800); /* flush_cache: */ -stl_raw(base + 0x534, 0xbfc00808); /* print: */ -stl_raw(base + 0x538, 0xbfc00800); /* reg_cpu_isr: */ -stl_raw(base + 0x53c, 0xbfc00800); /* unred_cpu_isr: */ -stl_raw(base + 0x540, 0xbfc00800); /* reg_ic_isr: */ -stl_raw(base + 0x544, 0xbfc00800); /* unred_ic_isr: */ -stl_raw(base + 0x548, 0xbfc00800); /* reg_esr: */ -stl_raw(base + 0x54c, 0xbfc00800); /* unreg_esr: */ -stl_raw(base + 0x550, 0xbfc00800); /* getchar: */ -stl_raw(base + 0x554, 0xbfc00800); /* syscon_read: */ +stl_raw(base + 0x500, run_addr + 0x0580); /* start: */ +stl_raw(base + 0x504, run_addr + 0x083c); /* print_count: */ +stl_raw(base + 0x520, run_addr + 0x0580); /* start: */ +stl_raw(base + 0x52c, run_addr + 0x0800); /* flush_cache: */ +stl_raw(base + 0x534, run_addr + 0x0808); /* print: */ +stl_raw(base + 0x538, run_addr + 0x0800); /* reg_cpu_isr: */ +stl_raw(base + 0x53c, run_addr + 0x0800); /* unred_cpu_isr: */ +stl_raw(base + 0x540, run_addr + 0x0800); /* reg_ic_isr: */ +stl_raw(base + 0x544, run_addr + 0x0800); /* unred_ic_isr: */ +stl_raw(base + 0x548, run_addr + 0x0800); /* reg_esr: */ +stl_raw(base + 0x54c, run_addr + 0x0800); /* unreg_esr: */ +stl_raw(base + 0x550, run_addr + 0x0800); /* getchar: */ +stl_raw(base + 0x554, run_addr + 0x0800); /* syscon_read: */ /* Second part of the bootloader */ @@ -701,7 +704,7 @@ static void write_bootloader (CPUMIPSState *env, uint8_t *base, p = (uint32_t *) (base + 0x800); stl_raw(p++, 0x03e8); /* jr ra */ stl_raw(p++, 0x2402); /* li v0,0 */ - /* 808 YAMON print */ +/* 808 YAMON print */ stl_raw(p++, 0x03e06821); /* move t5,ra */ stl_raw(p++, 0x00805821); /* move t3,a0 */ stl_raw(p++, 0x00a05021); /* move t2,a1 */ @@ -774,6 +777,9 @@ static int64_t load_kernel (void) uint32_t *prom_buf; long prom_size; int prom_index = 0; +uint64_t (*xlate_to_phys) (void *opaque, uint64_t addr); +uint64_t (*xlate_to_kseg0) (void *opaque, uint64_t addr); + #ifdef TARGET_WORDS_BIGENDIAN big_endian = 1; @@ -781,7 +787,15 @@ static int64_t load_kernel (void) big_endian = 0; #endif -if (load_elf(loaderparams.kernel_filename, cpu_mips_kseg0_to_phys, NULL, +if (kvm_enabled()) { +xlate_to_phys = cpu_mips_kvm_um_kseg0_to_phys; +xlate_to_kseg0 = cpu_mips_kvm_um_phys_to_kseg0; +} else { +xlate_to_phys = cpu_mips_kseg0_to_phys; +xlate_to_kseg0 = cpu_mips_phys_to_kseg0; +} + +if (load_elf(loaderparams.kernel_filename, xlate_to_phys, NULL, (uint64_t *)&kernel_entry, NULL, (uint64_t *)&kernel_high,
Re: [Qemu-devel] [PATCH v3 6/9] target-mips: kvm: Add main KVM support for MIPS
Hi Andreas, On 13/03/14 21:28, Andreas Färber wrote: >> diff --git a/target-mips/kvm.c b/target-mips/kvm.c >> new file mode 100644 >> index 000..0ec343d >> --- /dev/null >> +++ b/target-mips/kvm.c > [...] >> +static inline int kvm_mips_put_one_reg(CPUState *cs, int reg_id, int32 >> *addr) > > Did you mean int32_t? >> +static inline int kvm_mips_get_one_reg(CPUState *cs, int reg_id, int32 >> *addr) > > int32_t? >> +*addr = (int32)val64; > > int32_t? > int32 is a type used in softfloat that has weird at-least-as-wide > semantics and bit us in the past. Well spotted, they should indeed be int32_t. > Otherwise looking good now, thanks for the CPU cleanups! We just had > another round of CPU refactorings go in today, but I don't spot a > conflict in this patch. Please rebase your local branch to verify. It rebased clearly, but I'll double check and send a v4 today anyway. Thanks James
Re: [Qemu-devel] [PATCH v3 6/9] target-mips: kvm: Add main KVM support for MIPS
On 13/03/14 22:35, Peter Maydell wrote: > On 13 March 2014 21:28, Andreas Färber wrote: >> I'm not sure if we have a policy about __u64 etc. in KVM code. Since >> it'll be Linux-only I don't see problems currently; for cross-platform >> parts we prefer uint64_t. Suggest to leave as is unless told otherwise. > > For ARM I took the view that __u64 were the kernel's types, not > ours. The kernel header structs define fields as __u64 but for > in-QEMU functions and variables we should use the posix uint64_t. Thanks, I'll follow that way then. Cheers James
[Qemu-devel] [PATCH v4 05/10] kvm: Allow arch to set sigmask length
MIPS/Linux is unusual in having 128 signals rather than just 64 like most other architectures. This means its sigmask is 16 bytes instead of 8, so allow arches to override the sigmask->len value passed to the KVM_SET_SIGNAL_MASK ioctl in kvm_set_signal_mask() by calling kvm_set_sigmask_len() from kvm_arch_init(). Otherwise default to 8 bytes. Signed-off-by: James Hogan Cc: Aurelien Jarno Cc: Sanjay Lal Cc: Gleb Natapov Cc: Paolo Bonzini Cc: Peter Maydell --- Changes in v3: - Rewrote to allow sigmask length to be set by kvm_arch_init(), so that MIPS can set it to 16 as it has 128 signals. This is better than cluttering kvm-all.c with TARGET_* ifdefs (Peter Maydell). Changes in v2: - Expand commit message - Reword comment --- include/sysemu/kvm.h | 2 ++ kvm-all.c| 11 ++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h index 0bee1e8..e9cdb0c 100644 --- a/include/sysemu/kvm.h +++ b/include/sysemu/kvm.h @@ -297,6 +297,8 @@ int kvm_check_extension(KVMState *s, unsigned int extension); uint32_t kvm_arch_get_supported_cpuid(KVMState *env, uint32_t function, uint32_t index, int reg); +void kvm_set_sigmask_len(KVMState *s, unsigned int sigmask_len); + #if !defined(CONFIG_USER_ONLY) int kvm_physical_memory_addr_from_host(KVMState *s, void *ram_addr, hwaddr *phys_addr); diff --git a/kvm-all.c b/kvm-all.c index 82a9119..d3be5ae 100644 --- a/kvm-all.c +++ b/kvm-all.c @@ -98,6 +98,7 @@ struct KVMState * they're not. Linux, glibc and *BSD all treat ioctl numbers as * unsigned, and treating them as signed here can break things */ unsigned irq_set_ioctl; +unsigned int sigmask_len; #ifdef KVM_CAP_IRQ_ROUTING struct kvm_irq_routing *irq_routes; int nr_allocated_irq_routes; @@ -1372,6 +1373,8 @@ int kvm_init(QEMUMachine *machine) assert(TARGET_PAGE_SIZE <= getpagesize()); page_size_init(); +s->sigmask_len = 8; + #ifdef KVM_CAP_SET_GUEST_DEBUG QTAILQ_INIT(&s->kvm_sw_breakpoints); #endif @@ -1548,6 +1551,11 @@ err: return ret; } +void kvm_set_sigmask_len(KVMState *s, unsigned int sigmask_len) +{ +s->sigmask_len = sigmask_len; +} + static void kvm_handle_io(uint16_t port, void *data, int direction, int size, uint32_t count) { @@ -2068,6 +2076,7 @@ void kvm_remove_all_breakpoints(CPUState *cpu) int kvm_set_signal_mask(CPUState *cpu, const sigset_t *sigset) { +KVMState *s = kvm_state; struct kvm_signal_mask *sigmask; int r; @@ -2077,7 +2086,7 @@ int kvm_set_signal_mask(CPUState *cpu, const sigset_t *sigset) sigmask = g_malloc(sizeof(*sigmask) + sizeof(*sigset)); -sigmask->len = 8; +sigmask->len = s->sigmask_len; memcpy(sigmask->sigset, sigset, sizeof(*sigset)); r = kvm_vcpu_ioctl(cpu, KVM_SET_SIGNAL_MASK, sigmask); g_free(sigmask); -- 1.8.1.2
[Qemu-devel] [PATCH v4 01/10] hw/mips/cputimer: Don't start periodic timer in KVM mode
From: Sanjay Lal Compare/Count timer interrupts are handled in-kernel for KVM, so don't bother starting it in QEMU. Signed-off-by: Sanjay Lal Signed-off-by: James Hogan Reviewed-by: Aurelien Jarno --- Changes in v2: - Expand commit message - Rebase on v1.7.0 - Wrap comment --- hw/mips/cputimer.c | 13 ++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/hw/mips/cputimer.c b/hw/mips/cputimer.c index c8b4b00..52570fd 100644 --- a/hw/mips/cputimer.c +++ b/hw/mips/cputimer.c @@ -23,6 +23,7 @@ #include "hw/hw.h" #include "hw/mips/cpudevs.h" #include "qemu/timer.h" +#include "sysemu/kvm.h" #define TIMER_FREQ 100 * 1000 * 1000 @@ -141,7 +142,13 @@ static void mips_timer_cb (void *opaque) void cpu_mips_clock_init (CPUMIPSState *env) { -env->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, &mips_timer_cb, env); -env->CP0_Compare = 0; -cpu_mips_store_count(env, 1); +/* + * If we're in KVM mode, don't start the periodic timer, that is handled in + * kernel. + */ +if (!kvm_enabled()) { +env->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, &mips_timer_cb, env); +env->CP0_Compare = 0; +cpu_mips_store_count(env, 1); +} } -- 1.8.1.2
[Qemu-devel] [PATCH v4 07/10] hw/mips: In KVM mode, inject IRQ2 (I/O) interupts via ioctls
From: Sanjay Lal COP0 emulation is in-kernel for KVM, so inject IRQ2 (I/O) interrupts via ioctls. Signed-off-by: Sanjay Lal Signed-off-by: James Hogan Reviewed-by: Aurelien Jarno Reviewed-by: Andreas Färber --- Changes in v3: - Pass MIPSCPU to kvm_mips_set_[ipi_]interrupt (Andreas Färber). Changes in v2: - Expand commit message - Remove #ifdef CONFIG_KVM since it's guarded by kvm_enabled() already --- hw/mips/mips_int.c | 11 +++ 1 file changed, 11 insertions(+) diff --git a/hw/mips/mips_int.c b/hw/mips/mips_int.c index 7dbd24d..d740046 100644 --- a/hw/mips/mips_int.c +++ b/hw/mips/mips_int.c @@ -23,6 +23,8 @@ #include "hw/hw.h" #include "hw/mips/cpudevs.h" #include "cpu.h" +#include "sysemu/kvm.h" +#include "kvm_mips.h" static void cpu_mips_irq_request(void *opaque, int irq, int level) { @@ -35,8 +37,17 @@ static void cpu_mips_irq_request(void *opaque, int irq, int level) if (level) { env->CP0_Cause |= 1 << (irq + CP0Ca_IP); + +if (kvm_enabled() && irq == 2) { +kvm_mips_set_interrupt(cpu, irq, level); +} + } else { env->CP0_Cause &= ~(1 << (irq + CP0Ca_IP)); + +if (kvm_enabled() && irq == 2) { +kvm_mips_set_interrupt(cpu, irq, level); +} } if (env->CP0_Cause & CP0Ca_IP_mask) { -- 1.8.1.2
[Qemu-devel] [PATCH v4 03/10] target-mips: get_physical_address: Add defines for segment bases
Add preprocessor definitions for 32bit segment bases for use in get_physical_address(). These will also be taken advantage of in the next patch which adds KVM awareness. Signed-off-by: James Hogan Reviewed-by: Aurelien Jarno --- target-mips/helper.c | 18 -- 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/target-mips/helper.c b/target-mips/helper.c index b28ae9b..2b30fc2 100644 --- a/target-mips/helper.c +++ b/target-mips/helper.c @@ -118,7 +118,13 @@ static int get_physical_address (CPUMIPSState *env, hwaddr *physical, qemu_log("user mode %d h %08x\n", user_mode, env->hflags); #endif -if (address <= (int32_t)0x7FFFUL) { +#define USEG_LIMIT 0x7FFFUL +#define KSEG0_BASE 0x8000UL +#define KSEG1_BASE 0xA000UL +#define KSEG2_BASE 0xC000UL +#define KSEG3_BASE 0xE000UL + +if (address <= USEG_LIMIT) { /* useg */ if (env->CP0_Status & (1 << CP0St_ERL)) { *physical = address & 0x; @@ -160,23 +166,23 @@ static int get_physical_address (CPUMIPSState *env, hwaddr *physical, ret = TLBRET_BADADDR; } #endif -} else if (address < (int32_t)0xA000UL) { +} else if (address < (int32_t)KSEG1_BASE) { /* kseg0 */ if (kernel_mode) { -*physical = address - (int32_t)0x8000UL; +*physical = address - (int32_t)KSEG0_BASE; *prot = PAGE_READ | PAGE_WRITE; } else { ret = TLBRET_BADADDR; } -} else if (address < (int32_t)0xC000UL) { +} else if (address < (int32_t)KSEG2_BASE) { /* kseg1 */ if (kernel_mode) { -*physical = address - (int32_t)0xA000UL; +*physical = address - (int32_t)KSEG1_BASE; *prot = PAGE_READ | PAGE_WRITE; } else { ret = TLBRET_BADADDR; } -} else if (address < (int32_t)0xE000UL) { +} else if (address < (int32_t)KSEG3_BASE) { /* sseg (kseg2) */ if (supervisor_mode || kernel_mode) { ret = env->tlb->map_address(env, physical, prot, address, rw, access_type); -- 1.8.1.2