MIPS patches 2017-08-03
Changes: KVM T&E segment support for TCG malta: leave space for the bootmap after the initrd Apply CP0.PageMask before writing into TLB entry Fix fallout from indirect branch optimisation -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.5 (GNU/Linux) iQIVAwUAWYM0GyI464bV95fCAQLhcw/9EBGDoCKgDGtriMOs6XhJjiGyQi0WZ2js kVjcS0jbyyIXgjLAfH33Gbn5/23pJy1rTk9I+ERqqtMgwdnX2zLWax6cm2NM4+hI IGuP3rIK0W2ETHRpn8UPA4G89PVh6Q46QW3Cu4jEd699fDZHAQx+YMhEr1RT3m6V zWpzH2Myt2DrbglBRAbt20CFZl0z6+OUcYi1Cw7aZ7t7+3hV+ZxLqAa9Vo64VslS 4bdTrFhpL1+AoxMilGWjNgeoeentsX8OZSl61pAq/vEgaoPT1S+ipmvdH5mAUwPp NOXM9A5OwLdWM1pTTLhcPPmdd9zeJbCtCoA1c6CXtULe1oX3MtT/TFvqAV8ALpar XffbDk90PyB3cMvFIBjSKmQGVEl580rS7db9G0LMfw9ZnxWKE0txf/qD40MMfG8O HQbuazVT8A40VjbF6hPS0rJliI+q+sKChp7ug27PSf22fnEYsPlctgiSYMA44uF8 HzbgS0jqMNDaKCw+rehxVMQiR1J6sGOt/XLbSkG32l5Qjo6NoYoffC95AGp9R3nH DyW8nKrCZsrYXf/nsvAqgWo4ceEGu9xL5hKUfCLFGkgnBzGxyrAYlO0m043/YHbU LXJKeq5oN0mqRpZkDZan8P2irL2SaX+kDJeA07Z6xxuQDn+qC4fp2G8HXkNU3n/7 iQ+XqMDECSE= =R2lj -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/yongbok/tags/mips-20170803' into staging MIPS patches 2017-08-03 Changes: KVM T&E segment support for TCG malta: leave space for the bootmap after the initrd Apply CP0.PageMask before writing into TLB entry Fix fallout from indirect branch optimisation # gpg: Signature made Thu 03 Aug 2017 15:32:59 BST # gpg: using RSA key 0x2238EB86D5F797C2 # gpg: Good signature from "Yongbok Kim <yongbok.kim@imgtec.com>" # gpg: WARNING: This key is not certified with sufficiently trusted signatures! # gpg: It is not certain that the signature belongs to the owner. # Primary key fingerprint: 8600 4CF5 3415 A5D9 4CFA 2B5C 2238 EB86 D5F7 97C2 * remotes/yongbok/tags/mips-20170803: target/mips: Fix RDHWR CC with icount target/mips: Drop redundant gen_io_start/stop() target/mips: Use BS_EXCP where interrupts are expected target-mips: apply CP0.PageMask before writing into TLB entry mips: Add KVM T&E segment support for TCG mips: Improve segment defs for KVM T&E guests mips/malta: leave space for the bootmap after the initrd target-mips: Don't stop on [d]mtc0 DESAVE/KScratch Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
c233a35d3d
@ -24,6 +24,8 @@
|
||||
#include "hw/hw.h"
|
||||
#include "hw/mips/cpudevs.h"
|
||||
|
||||
static int mips_um_ksegs;
|
||||
|
||||
uint64_t cpu_mips_kseg0_to_phys(void *opaque, uint64_t addr)
|
||||
{
|
||||
return addr & 0x1fffffffll;
|
||||
@ -38,3 +40,13 @@ uint64_t cpu_mips_kvm_um_phys_to_kseg0(void *opaque, uint64_t addr)
|
||||
{
|
||||
return addr | 0x40000000ll;
|
||||
}
|
||||
|
||||
bool mips_um_ksegs_enabled(void)
|
||||
{
|
||||
return mips_um_ksegs;
|
||||
}
|
||||
|
||||
void mips_um_ksegs_enable(void)
|
||||
{
|
||||
mips_um_ksegs = 1;
|
||||
}
|
||||
|
@ -818,23 +818,20 @@ static int64_t load_kernel (void)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Sanity check where the kernel has been linked */
|
||||
if (kvm_enabled()) {
|
||||
if (kernel_entry & 0x80000000ll) {
|
||||
/* Check where the kernel has been linked */
|
||||
if (kernel_entry & 0x80000000ll) {
|
||||
if (kvm_enabled()) {
|
||||
error_report("KVM guest kernels must be linked in useg. "
|
||||
"Did you forget to enable CONFIG_KVM_GUEST?");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
xlate_to_kseg0 = cpu_mips_kvm_um_phys_to_kseg0;
|
||||
} else {
|
||||
if (!(kernel_entry & 0x80000000ll)) {
|
||||
error_report("KVM guest kernels aren't supported with TCG. "
|
||||
"Did you unintentionally enable CONFIG_KVM_GUEST?");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
xlate_to_kseg0 = cpu_mips_phys_to_kseg0;
|
||||
} else {
|
||||
/* if kernel entry is in useg it is probably a KVM T&E kernel */
|
||||
mips_um_ksegs_enable();
|
||||
|
||||
xlate_to_kseg0 = cpu_mips_kvm_um_phys_to_kseg0;
|
||||
}
|
||||
|
||||
/* load initrd */
|
||||
@ -843,7 +840,10 @@ static int64_t load_kernel (void)
|
||||
if (loaderparams.initrd_filename) {
|
||||
initrd_size = get_image_size (loaderparams.initrd_filename);
|
||||
if (initrd_size > 0) {
|
||||
initrd_offset = (loaderparams.ram_low_size - initrd_size
|
||||
/* The kernel allocates the bootmap memory in the low memory after
|
||||
the initrd. It takes at most 128kiB for 2GB RAM and 4kiB
|
||||
pages. */
|
||||
initrd_offset = (loaderparams.ram_low_size - initrd_size - 131072
|
||||
- ~INITRD_PAGE_MASK) & INITRD_PAGE_MASK;
|
||||
if (kernel_high >= initrd_offset) {
|
||||
fprintf(stderr,
|
||||
|
@ -5,11 +5,12 @@
|
||||
|
||||
/* Definitions for MIPS CPU internal devices. */
|
||||
|
||||
/* mips_addr.c */
|
||||
/* 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);
|
||||
|
||||
bool mips_um_ksegs_enabled(void);
|
||||
void mips_um_ksegs_enable(void);
|
||||
|
||||
/* mips_int.c */
|
||||
void cpu_mips_irq_init_cpu(MIPSCPU *cpu);
|
||||
|
@ -19,10 +19,10 @@
|
||||
#include "qemu/osdep.h"
|
||||
|
||||
#include "cpu.h"
|
||||
#include "sysemu/kvm.h"
|
||||
#include "exec/exec-all.h"
|
||||
#include "exec/cpu_ldst.h"
|
||||
#include "exec/log.h"
|
||||
#include "hw/mips/cpudevs.h"
|
||||
|
||||
enum {
|
||||
TLBRET_XI = -6,
|
||||
@ -216,16 +216,16 @@ static int get_physical_address (CPUMIPSState *env, hwaddr *physical,
|
||||
/* effective address (modified for KVM T&E kernel segments) */
|
||||
target_ulong address = real_address;
|
||||
|
||||
#define USEG_LIMIT 0x7FFFFFFFUL
|
||||
#define KSEG0_BASE 0x80000000UL
|
||||
#define KSEG1_BASE 0xA0000000UL
|
||||
#define KSEG2_BASE 0xC0000000UL
|
||||
#define KSEG3_BASE 0xE0000000UL
|
||||
#define USEG_LIMIT ((target_ulong)(int32_t)0x7FFFFFFFUL)
|
||||
#define KSEG0_BASE ((target_ulong)(int32_t)0x80000000UL)
|
||||
#define KSEG1_BASE ((target_ulong)(int32_t)0xA0000000UL)
|
||||
#define KSEG2_BASE ((target_ulong)(int32_t)0xC0000000UL)
|
||||
#define KSEG3_BASE ((target_ulong)(int32_t)0xE0000000UL)
|
||||
|
||||
#define KVM_KSEG0_BASE 0x40000000UL
|
||||
#define KVM_KSEG2_BASE 0x60000000UL
|
||||
#define KVM_KSEG0_BASE ((target_ulong)(int32_t)0x40000000UL)
|
||||
#define KVM_KSEG2_BASE ((target_ulong)(int32_t)0x60000000UL)
|
||||
|
||||
if (kvm_enabled()) {
|
||||
if (mips_um_ksegs_enabled()) {
|
||||
/* KVM T&E adds guest kernel segments in useg */
|
||||
if (real_address >= KVM_KSEG0_BASE) {
|
||||
if (real_address < KVM_KSEG2_BASE) {
|
||||
@ -307,17 +307,17 @@ static int get_physical_address (CPUMIPSState *env, hwaddr *physical,
|
||||
ret = TLBRET_BADADDR;
|
||||
}
|
||||
#endif
|
||||
} else if (address < (int32_t)KSEG1_BASE) {
|
||||
} else if (address < KSEG1_BASE) {
|
||||
/* kseg0 */
|
||||
ret = get_segctl_physical_address(env, physical, prot, real_address, rw,
|
||||
access_type, mmu_idx,
|
||||
env->CP0_SegCtl1 >> 16, 0x1FFFFFFF);
|
||||
} else if (address < (int32_t)KSEG2_BASE) {
|
||||
} else if (address < KSEG2_BASE) {
|
||||
/* kseg1 */
|
||||
ret = get_segctl_physical_address(env, physical, prot, real_address, rw,
|
||||
access_type, mmu_idx,
|
||||
env->CP0_SegCtl1, 0x1FFFFFFF);
|
||||
} else if (address < (int32_t)KSEG3_BASE) {
|
||||
} else if (address < KSEG3_BASE) {
|
||||
/* sseg (kseg2) */
|
||||
ret = get_segctl_physical_address(env, physical, prot, real_address, rw,
|
||||
access_type, mmu_idx,
|
||||
@ -974,8 +974,7 @@ void mips_cpu_do_interrupt(CPUState *cs)
|
||||
} else if (cause == 30 && !(env->CP0_Config3 & (1 << CP0C3_SC) &&
|
||||
env->CP0_Config5 & (1 << CP0C5_CV))) {
|
||||
/* Force KSeg1 for cache errors */
|
||||
env->active_tc.PC = (int32_t)KSEG1_BASE |
|
||||
(env->CP0_EBase & 0x1FFFF000);
|
||||
env->active_tc.PC = KSEG1_BASE | (env->CP0_EBase & 0x1FFFF000);
|
||||
} else {
|
||||
env->active_tc.PC = env->CP0_EBase & ~0xfff;
|
||||
}
|
||||
|
@ -2008,6 +2008,7 @@ static inline uint64_t get_tlb_pfn_from_entrylo(uint64_t entrylo)
|
||||
static void r4k_fill_tlb(CPUMIPSState *env, int idx)
|
||||
{
|
||||
r4k_tlb_t *tlb;
|
||||
uint64_t mask = env->CP0_PageMask >> (TARGET_PAGE_BITS + 1);
|
||||
|
||||
/* XXX: detect conflicting TLBs and raise a MCHECK exception when needed */
|
||||
tlb = &env->tlb->mmu.r4k.tlb[idx];
|
||||
@ -2028,13 +2029,13 @@ static void r4k_fill_tlb(CPUMIPSState *env, int idx)
|
||||
tlb->C0 = (env->CP0_EntryLo0 >> 3) & 0x7;
|
||||
tlb->XI0 = (env->CP0_EntryLo0 >> CP0EnLo_XI) & 1;
|
||||
tlb->RI0 = (env->CP0_EntryLo0 >> CP0EnLo_RI) & 1;
|
||||
tlb->PFN[0] = get_tlb_pfn_from_entrylo(env->CP0_EntryLo0) << 12;
|
||||
tlb->PFN[0] = (get_tlb_pfn_from_entrylo(env->CP0_EntryLo0) & ~mask) << 12;
|
||||
tlb->V1 = (env->CP0_EntryLo1 & 2) != 0;
|
||||
tlb->D1 = (env->CP0_EntryLo1 & 4) != 0;
|
||||
tlb->C1 = (env->CP0_EntryLo1 >> 3) & 0x7;
|
||||
tlb->XI1 = (env->CP0_EntryLo1 >> CP0EnLo_XI) & 1;
|
||||
tlb->RI1 = (env->CP0_EntryLo1 >> CP0EnLo_RI) & 1;
|
||||
tlb->PFN[1] = get_tlb_pfn_from_entrylo(env->CP0_EntryLo1) << 12;
|
||||
tlb->PFN[1] = (get_tlb_pfn_from_entrylo(env->CP0_EntryLo1) & ~mask) << 12;
|
||||
}
|
||||
|
||||
void r4k_helper_tlbinv(CPUMIPSState *env)
|
||||
|
@ -27,10 +27,10 @@
|
||||
#include "exec/exec-all.h"
|
||||
#include "tcg-op.h"
|
||||
#include "exec/cpu_ldst.h"
|
||||
#include "hw/mips/cpudevs.h"
|
||||
|
||||
#include "exec/helper-proto.h"
|
||||
#include "exec/helper-gen.h"
|
||||
#include "sysemu/kvm.h"
|
||||
#include "exec/semihost.h"
|
||||
|
||||
#include "target/mips/trace.h"
|
||||
@ -5334,8 +5334,10 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
|
||||
gen_io_end();
|
||||
}
|
||||
/* Break the TB to be able to take timer interrupts immediately
|
||||
after reading count. */
|
||||
ctx->bstate = BS_STOP;
|
||||
after reading count. BS_STOP isn't sufficient, we need to ensure
|
||||
we break completely out of translated code. */
|
||||
gen_save_pc(ctx->pc + 4);
|
||||
ctx->bstate = BS_EXCP;
|
||||
rn = "Count";
|
||||
break;
|
||||
/* 6,7 are implementation dependent */
|
||||
@ -6061,6 +6063,11 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
|
||||
case 0:
|
||||
save_cpu_state(ctx, 1);
|
||||
gen_helper_mtc0_cause(cpu_env, arg);
|
||||
/* Stop translation as we may have triggered an interrupt. BS_STOP
|
||||
* isn't sufficient, we need to ensure we break out of translated
|
||||
* code to check for pending interrupts. */
|
||||
gen_save_pc(ctx->pc + 4);
|
||||
ctx->bstate = BS_EXCP;
|
||||
rn = "Cause";
|
||||
break;
|
||||
default:
|
||||
@ -6386,8 +6393,6 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
|
||||
default:
|
||||
goto cp0_unimplemented;
|
||||
}
|
||||
/* Stop translation as we may have switched the execution mode */
|
||||
ctx->bstate = BS_STOP;
|
||||
break;
|
||||
default:
|
||||
goto cp0_unimplemented;
|
||||
@ -6397,7 +6402,10 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
|
||||
/* For simplicity assume that all writes can cause interrupts. */
|
||||
if (ctx->tb->cflags & CF_USE_ICOUNT) {
|
||||
gen_io_end();
|
||||
ctx->bstate = BS_STOP;
|
||||
/* BS_STOP isn't sufficient, we need to ensure we break out of
|
||||
* translated code to check for pending interrupts. */
|
||||
gen_save_pc(ctx->pc + 4);
|
||||
ctx->bstate = BS_EXCP;
|
||||
}
|
||||
return;
|
||||
|
||||
@ -6678,8 +6686,10 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
|
||||
gen_io_end();
|
||||
}
|
||||
/* Break the TB to be able to take timer interrupts immediately
|
||||
after reading count. */
|
||||
ctx->bstate = BS_STOP;
|
||||
after reading count. BS_STOP isn't sufficient, we need to ensure
|
||||
we break completely out of translated code. */
|
||||
gen_save_pc(ctx->pc + 4);
|
||||
ctx->bstate = BS_EXCP;
|
||||
rn = "Count";
|
||||
break;
|
||||
/* 6,7 are implementation dependent */
|
||||
@ -7391,17 +7401,12 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
|
||||
switch (sel) {
|
||||
case 0:
|
||||
save_cpu_state(ctx, 1);
|
||||
/* Mark as an IO operation because we may trigger a software
|
||||
interrupt. */
|
||||
if (ctx->tb->cflags & CF_USE_ICOUNT) {
|
||||
gen_io_start();
|
||||
}
|
||||
gen_helper_mtc0_cause(cpu_env, arg);
|
||||
if (ctx->tb->cflags & CF_USE_ICOUNT) {
|
||||
gen_io_end();
|
||||
}
|
||||
/* Stop translation as we may have triggered an intetrupt */
|
||||
ctx->bstate = BS_STOP;
|
||||
/* Stop translation as we may have triggered an intetrupt. BS_STOP
|
||||
* isn't sufficient, we need to ensure we break out of translated
|
||||
* code to check for pending interrupts. */
|
||||
gen_save_pc(ctx->pc + 4);
|
||||
ctx->bstate = BS_EXCP;
|
||||
rn = "Cause";
|
||||
break;
|
||||
default:
|
||||
@ -7714,8 +7719,6 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
|
||||
default:
|
||||
goto cp0_unimplemented;
|
||||
}
|
||||
/* Stop translation as we may have switched the execution mode */
|
||||
ctx->bstate = BS_STOP;
|
||||
break;
|
||||
default:
|
||||
goto cp0_unimplemented;
|
||||
@ -7725,7 +7728,10 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
|
||||
/* For simplicity assume that all writes can cause interrupts. */
|
||||
if (ctx->tb->cflags & CF_USE_ICOUNT) {
|
||||
gen_io_end();
|
||||
ctx->bstate = BS_STOP;
|
||||
/* BS_STOP isn't sufficient, we need to ensure we break out of
|
||||
* translated code to check for pending interrupts. */
|
||||
gen_save_pc(ctx->pc + 4);
|
||||
ctx->bstate = BS_EXCP;
|
||||
}
|
||||
return;
|
||||
|
||||
@ -10749,8 +10755,19 @@ static void gen_rdhwr(DisasContext *ctx, int rt, int rd, int sel)
|
||||
gen_store_gpr(t0, rt);
|
||||
break;
|
||||
case 2:
|
||||
if (ctx->tb->cflags & CF_USE_ICOUNT) {
|
||||
gen_io_start();
|
||||
}
|
||||
gen_helper_rdhwr_cc(t0, cpu_env);
|
||||
if (ctx->tb->cflags & CF_USE_ICOUNT) {
|
||||
gen_io_end();
|
||||
}
|
||||
gen_store_gpr(t0, rt);
|
||||
/* Break the TB to be able to take timer interrupts immediately
|
||||
after reading count. BS_STOP isn't sufficient, we need to ensure
|
||||
we break completely out of translated code. */
|
||||
gen_save_pc(ctx->pc + 4);
|
||||
ctx->bstate = BS_EXCP;
|
||||
break;
|
||||
case 3:
|
||||
gen_helper_rdhwr_ccres(t0, cpu_env);
|
||||
@ -13569,8 +13586,10 @@ static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs)
|
||||
save_cpu_state(ctx, 1);
|
||||
gen_helper_ei(t0, cpu_env);
|
||||
gen_store_gpr(t0, rs);
|
||||
/* Stop translation as we may have switched the execution mode */
|
||||
ctx->bstate = BS_STOP;
|
||||
/* BS_STOP isn't sufficient, we need to ensure we break out
|
||||
of translated code to check for pending interrupts. */
|
||||
gen_save_pc(ctx->pc + 4);
|
||||
ctx->bstate = BS_EXCP;
|
||||
tcg_temp_free(t0);
|
||||
}
|
||||
break;
|
||||
@ -19692,9 +19711,10 @@ static void decode_opc(CPUMIPSState *env, DisasContext *ctx)
|
||||
save_cpu_state(ctx, 1);
|
||||
gen_helper_ei(t0, cpu_env);
|
||||
gen_store_gpr(t0, rt);
|
||||
/* Stop translation as we may have switched
|
||||
the execution mode. */
|
||||
ctx->bstate = BS_STOP;
|
||||
/* BS_STOP isn't sufficient, we need to ensure we break out
|
||||
of translated code to check for pending interrupts. */
|
||||
gen_save_pc(ctx->pc + 4);
|
||||
ctx->bstate = BS_EXCP;
|
||||
break;
|
||||
default: /* Invalid */
|
||||
MIPS_INVAL("mfmc0");
|
||||
@ -20639,7 +20659,7 @@ void cpu_state_reset(CPUMIPSState *env)
|
||||
env->CP0_Wired = 0;
|
||||
env->CP0_GlobalNumber = (cs->cpu_index & 0xFF) << CP0GN_VPId;
|
||||
env->CP0_EBase = (cs->cpu_index & 0x3FF);
|
||||
if (kvm_enabled()) {
|
||||
if (mips_um_ksegs_enabled()) {
|
||||
env->CP0_EBase |= 0x40000000;
|
||||
} else {
|
||||
env->CP0_EBase |= (int32_t)0x80000000;
|
||||
|
Loading…
Reference in New Issue
Block a user