Commit c233a35d authored by Peter Maydell's avatar Peter Maydell
Browse files

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: default avatarPeter Maydell <peter.maydell@linaro.org>
parents 8377e9f6 d673a68d
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -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;
}
+11 −11
Original line number Diff line number Diff line
@@ -818,23 +818,20 @@ static int64_t load_kernel (void)
        exit(1);
    }

    /* Sanity check where the kernel has been linked */
    if (kvm_enabled()) {
    /* 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;
        xlate_to_kseg0 = cpu_mips_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);
        }
        /* if kernel entry is in useg it is probably a KVM T&E kernel */
        mips_um_ksegs_enable();

        xlate_to_kseg0 = cpu_mips_phys_to_kseg0;
        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,
+3 −2
Original line number Diff line number Diff line
@@ -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);
+13 −14
Original line number Diff line number Diff line
@@ -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;
        }
+3 −2
Original line number Diff line number Diff line
@@ -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)
Loading