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

Merge remote-tracking branch 'remotes/davidhildenbrand/tags/s390x-tcg-2019-10-10' into staging



- MMU DAT translation rewrite and cleanup
- Implement more TCG CPU features related to the MMU (e.g., IEP)
- Add the current instruction length to unwind data and clean up
- Resolve one TODO for the MVCL instruction

# gpg: Signature made Thu 10 Oct 2019 12:25:06 BST
# gpg:                using RSA key 1BD9CAAD735C4C3A460DFCCA4DDE10F700FF835A
# gpg:                issuer "david@redhat.com"
# gpg: Good signature from "David Hildenbrand <david@redhat.com>" [unknown]
# gpg:                 aka "David Hildenbrand <davidhildenbrand@gmail.com>" [full]
# Primary key fingerprint: 1BD9 CAAD 735C 4C3A 460D  FCCA 4DDE 10F7 00FF 835A

* remotes/davidhildenbrand/tags/s390x-tcg-2019-10-10: (31 commits)
  s390x/tcg: MVCL: Exit to main loop if requested
  target/s390x: Remove ILEN_UNWIND
  target/s390x: Remove ilen argument from trigger_pgm_exception
  target/s390x: Remove ilen argument from trigger_access_exception
  target/s390x: Remove ILEN_AUTO
  target/s390x: Rely on unwinding in s390_cpu_virt_mem_rw
  target/s390x: Rely on unwinding in s390_cpu_tlb_fill
  target/s390x: Simplify helper_lra
  target/s390x: Remove fail variable from s390_cpu_tlb_fill
  target/s390x: Return exception from translate_pages
  target/s390x: Return exception from mmu_translate
  target/s390x: Remove exc argument to mmu_translate_asce
  target/s390x: Return exception from mmu_translate_real
  target/s390x: Handle tec in s390_cpu_tlb_fill
  target/s390x: Push trigger_pgm_exception lower in s390_cpu_tlb_fill
  target/s390x: Use tcg_s390_program_interrupt in TCG helpers
  target/s390x: Remove ilen parameter from s390_program_interrupt
  target/s390x: Remove ilen parameter from tcg_s390_program_interrupt
  target/s390x: Add ilen to unwind data
  s390x/cpumodel: Add new TCG features to QEMU cpu model
  ...

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents 98b2e3c9 1f6493be
Loading
Loading
Loading
Loading
+29 −29
Original line number Diff line number Diff line
@@ -157,7 +157,7 @@ int clp_service_call(S390CPU *cpu, uint8_t r2, uintptr_t ra)
    int i;

    if (env->psw.mask & PSW_MASK_PSTATE) {
        s390_program_interrupt(env, PGM_PRIVILEGED, 4, ra);
        s390_program_interrupt(env, PGM_PRIVILEGED, ra);
        return 0;
    }

@@ -168,7 +168,7 @@ int clp_service_call(S390CPU *cpu, uint8_t r2, uintptr_t ra)
    reqh = (ClpReqHdr *)buffer;
    req_len = lduw_p(&reqh->len);
    if (req_len < 16 || req_len > 8184 || (req_len % 8 != 0)) {
        s390_program_interrupt(env, PGM_OPERAND, 4, ra);
        s390_program_interrupt(env, PGM_OPERAND, ra);
        return 0;
    }

@@ -180,11 +180,11 @@ int clp_service_call(S390CPU *cpu, uint8_t r2, uintptr_t ra)
    resh = (ClpRspHdr *)(buffer + req_len);
    res_len = lduw_p(&resh->len);
    if (res_len < 8 || res_len > 8176 || (res_len % 8 != 0)) {
        s390_program_interrupt(env, PGM_OPERAND, 4, ra);
        s390_program_interrupt(env, PGM_OPERAND, ra);
        return 0;
    }
    if ((req_len + res_len) > 8192) {
        s390_program_interrupt(env, PGM_OPERAND, 4, ra);
        s390_program_interrupt(env, PGM_OPERAND, ra);
        return 0;
    }

@@ -390,12 +390,12 @@ int pcilg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2, uintptr_t ra)
    uint8_t pcias;

    if (env->psw.mask & PSW_MASK_PSTATE) {
        s390_program_interrupt(env, PGM_PRIVILEGED, 4, ra);
        s390_program_interrupt(env, PGM_PRIVILEGED, ra);
        return 0;
    }

    if (r2 & 0x1) {
        s390_program_interrupt(env, PGM_SPECIFICATION, 4, ra);
        s390_program_interrupt(env, PGM_SPECIFICATION, ra);
        return 0;
    }

@@ -429,25 +429,25 @@ int pcilg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2, uintptr_t ra)
    switch (pcias) {
    case ZPCI_IO_BAR_MIN...ZPCI_IO_BAR_MAX:
        if (!len || (len > (8 - (offset & 0x7)))) {
            s390_program_interrupt(env, PGM_OPERAND, 4, ra);
            s390_program_interrupt(env, PGM_OPERAND, ra);
            return 0;
        }
        result = zpci_read_bar(pbdev, pcias, offset, &data, len);
        if (result != MEMTX_OK) {
            s390_program_interrupt(env, PGM_OPERAND, 4, ra);
            s390_program_interrupt(env, PGM_OPERAND, ra);
            return 0;
        }
        break;
    case ZPCI_CONFIG_BAR:
        if (!len || (len > (4 - (offset & 0x3))) || len == 3) {
            s390_program_interrupt(env, PGM_OPERAND, 4, ra);
            s390_program_interrupt(env, PGM_OPERAND, ra);
            return 0;
        }
        data =  pci_host_config_read_common(
                   pbdev->pdev, offset, pci_config_size(pbdev->pdev), len);

        if (zpci_endian_swap(&data, len)) {
            s390_program_interrupt(env, PGM_OPERAND, 4, ra);
            s390_program_interrupt(env, PGM_OPERAND, ra);
            return 0;
        }
        break;
@@ -489,12 +489,12 @@ int pcistg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2, uintptr_t ra)
    uint8_t pcias;

    if (env->psw.mask & PSW_MASK_PSTATE) {
        s390_program_interrupt(env, PGM_PRIVILEGED, 4, ra);
        s390_program_interrupt(env, PGM_PRIVILEGED, ra);
        return 0;
    }

    if (r2 & 0x1) {
        s390_program_interrupt(env, PGM_SPECIFICATION, 4, ra);
        s390_program_interrupt(env, PGM_SPECIFICATION, ra);
        return 0;
    }

@@ -536,13 +536,13 @@ int pcistg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2, uintptr_t ra)
         * A length of 0 is invalid and length should not cross a double word
         */
        if (!len || (len > (8 - (offset & 0x7)))) {
            s390_program_interrupt(env, PGM_OPERAND, 4, ra);
            s390_program_interrupt(env, PGM_OPERAND, ra);
            return 0;
        }

        result = zpci_write_bar(pbdev, pcias, offset, data, len);
        if (result != MEMTX_OK) {
            s390_program_interrupt(env, PGM_OPERAND, 4, ra);
            s390_program_interrupt(env, PGM_OPERAND, ra);
            return 0;
        }
        break;
@@ -550,7 +550,7 @@ int pcistg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2, uintptr_t ra)
        /* ZPCI uses the pseudo BAR number 15 as configuration space */
        /* possible access lengths are 1,2,4 and must not cross a word */
        if (!len || (len > (4 - (offset & 0x3))) || len == 3) {
            s390_program_interrupt(env, PGM_OPERAND, 4, ra);
            s390_program_interrupt(env, PGM_OPERAND, ra);
            return 0;
        }
        /* len = 1,2,4 so we do not need to test */
@@ -622,12 +622,12 @@ int rpcit_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2, uintptr_t ra)
    hwaddr start, end;

    if (env->psw.mask & PSW_MASK_PSTATE) {
        s390_program_interrupt(env, PGM_PRIVILEGED, 4, ra);
        s390_program_interrupt(env, PGM_PRIVILEGED, ra);
        return 0;
    }

    if (r2 & 0x1) {
        s390_program_interrupt(env, PGM_SPECIFICATION, 4, ra);
        s390_program_interrupt(env, PGM_SPECIFICATION, ra);
        return 0;
    }

@@ -709,7 +709,7 @@ int pcistb_service_call(S390CPU *cpu, uint8_t r1, uint8_t r3, uint64_t gaddr,
    uint8_t buffer[128];

    if (env->psw.mask & PSW_MASK_PSTATE) {
        s390_program_interrupt(env, PGM_PRIVILEGED, 6, ra);
        s390_program_interrupt(env, PGM_PRIVILEGED, ra);
        return 0;
    }

@@ -772,7 +772,7 @@ int pcistb_service_call(S390CPU *cpu, uint8_t r1, uint8_t r3, uint64_t gaddr,

    if (!memory_region_access_valid(mr, offset, len, true,
                                    MEMTXATTRS_UNSPECIFIED)) {
        s390_program_interrupt(env, PGM_OPERAND, 6, ra);
        s390_program_interrupt(env, PGM_OPERAND, ra);
        return 0;
    }

@@ -786,7 +786,7 @@ int pcistb_service_call(S390CPU *cpu, uint8_t r1, uint8_t r3, uint64_t gaddr,
                                              ldq_p(buffer + i * 8),
                                              MO_64, MEMTXATTRS_UNSPECIFIED);
        if (result != MEMTX_OK) {
            s390_program_interrupt(env, PGM_OPERAND, 6, ra);
            s390_program_interrupt(env, PGM_OPERAND, ra);
            return 0;
        }
    }
@@ -797,7 +797,7 @@ int pcistb_service_call(S390CPU *cpu, uint8_t r1, uint8_t r3, uint64_t gaddr,
    return 0;

specification_error:
    s390_program_interrupt(env, PGM_SPECIFICATION, 6, ra);
    s390_program_interrupt(env, PGM_SPECIFICATION, ra);
    return 0;
}

@@ -871,14 +871,14 @@ static int reg_ioat(CPUS390XState *env, S390PCIIOMMU *iommu, ZpciFib fib,
    pba &= ~0xfff;
    pal |= 0xfff;
    if (pba > pal || pba < ZPCI_SDMA_ADDR || pal > ZPCI_EDMA_ADDR) {
        s390_program_interrupt(env, PGM_OPERAND, 6, ra);
        s390_program_interrupt(env, PGM_OPERAND, ra);
        return -EINVAL;
    }

    /* currently we only support designation type 1 with translation */
    if (!(dt == ZPCI_IOTA_RTTO && t)) {
        error_report("unsupported ioat dt %d t %d", dt, t);
        s390_program_interrupt(env, PGM_OPERAND, 6, ra);
        s390_program_interrupt(env, PGM_OPERAND, ra);
        return -EINVAL;
    }

@@ -1003,7 +1003,7 @@ int mpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar,
    uint64_t cc = ZPCI_PCI_LS_OK;

    if (env->psw.mask & PSW_MASK_PSTATE) {
        s390_program_interrupt(env, PGM_PRIVILEGED, 6, ra);
        s390_program_interrupt(env, PGM_PRIVILEGED, ra);
        return 0;
    }

@@ -1012,7 +1012,7 @@ int mpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar,
    fh = env->regs[r1] >> 32;

    if (fiba & 0x7) {
        s390_program_interrupt(env, PGM_SPECIFICATION, 6, ra);
        s390_program_interrupt(env, PGM_SPECIFICATION, ra);
        return 0;
    }

@@ -1040,7 +1040,7 @@ int mpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar,
    }

    if (fib.fmt != 0) {
        s390_program_interrupt(env, PGM_OPERAND, 6, ra);
        s390_program_interrupt(env, PGM_OPERAND, ra);
        return 0;
    }

@@ -1151,7 +1151,7 @@ int mpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar,
        break;
    }
    default:
        s390_program_interrupt(&cpu->env, PGM_OPERAND, 6, ra);
        s390_program_interrupt(&cpu->env, PGM_OPERAND, ra);
        cc = ZPCI_PCI_LS_ERR;
    }

@@ -1171,7 +1171,7 @@ int stpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar,
    uint64_t cc = ZPCI_PCI_LS_OK;

    if (env->psw.mask & PSW_MASK_PSTATE) {
        s390_program_interrupt(env, PGM_PRIVILEGED, 6, ra);
        s390_program_interrupt(env, PGM_PRIVILEGED, ra);
        return 0;
    }

@@ -1185,7 +1185,7 @@ int stpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar,
    }

    if (fiba & 0x7) {
        s390_program_interrupt(env, PGM_SPECIFICATION, 6, ra);
        s390_program_interrupt(env, PGM_SPECIFICATION, ra);
        return 0;
    }

+2 −0
Original line number Diff line number Diff line
@@ -650,7 +650,9 @@ DEFINE_CCW_MACHINE(4_2, "4.2", true);

static void ccw_machine_4_1_instance_options(MachineState *machine)
{
    static const S390FeatInit qemu_cpu_feat = { S390_FEAT_LIST_QEMU_V4_1 };
    ccw_machine_4_2_instance_options(machine);
    s390_set_qemu_cpu_model(0x2964, 13, 2, qemu_cpu_feat);
}

static void ccw_machine_4_1_class_options(MachineClass *mc)
+17 −0
Original line number Diff line number Diff line
@@ -72,6 +72,23 @@ void QEMU_NORETURN cpu_loop_exit(CPUState *cpu);
void QEMU_NORETURN cpu_loop_exit_restore(CPUState *cpu, uintptr_t pc);
void QEMU_NORETURN cpu_loop_exit_atomic(CPUState *cpu, uintptr_t pc);

/**
 * cpu_loop_exit_requested:
 * @cpu: The CPU state to be tested
 *
 * Indicate if somebody asked for a return of the CPU to the main loop
 * (e.g., via cpu_exit() or cpu_interrupt()).
 *
 * This is helpful for architectures that support interruptible
 * instructions. After writing back all state to registers/memory, this
 * call can be used to check if it makes sense to return to the main loop
 * or to continue executing the interruptible instruction.
 */
static inline bool cpu_loop_exit_requested(CPUState *cpu)
{
    return (int32_t)atomic_read(&cpu_neg(cpu)->icount_decr.u32) < 0;
}

#if !defined(CONFIG_USER_ONLY)
void cpu_reloading_memory_map(void);
/**
+2 −2
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@
#include "qemu/osdep.h"
#include "cpu.h"
#include "internal.h"
#include "tcg_s390x.h"
#include "exec/exec-all.h"
#include "exec/helper-proto.h"
#include "qemu/host-utils.h"
@@ -588,8 +589,7 @@ void HELPER(sacf)(CPUS390XState *env, uint64_t a1)
        break;
    default:
        HELPER_LOG("unknown sacf mode: %" PRIx64 "\n", a1);
        s390_program_interrupt(env, PGM_SPECIFICATION, 2, GETPC());
        break;
        tcg_s390_program_interrupt(env, PGM_SPECIFICATION, GETPC());
    }
}
#endif
+61 −25
Original line number Diff line number Diff line
/*
 * S/390 virtual CPU header
 *
 * For details on the s390x architecture and used definitions (e.g.,
 * PSW, PER and DAT (Dynamic Address Translation)), please refer to
 * the "z/Architecture Principles of Operations" - a.k.a. PoP.
 *
 *  Copyright (c) 2009 Ulrich Hecht
 *  Copyright IBM Corp. 2012, 2018
 *
@@ -30,7 +34,7 @@
/* The z/Architecture has a strong memory model with some store-after-load re-ordering */
#define TCG_GUEST_DEFAULT_MO      (TCG_MO_ALL & ~TCG_MO_ST_LD)

#define TARGET_INSN_START_EXTRA_WORDS 1
#define TARGET_INSN_START_EXTRA_WORDS 2

#define MMU_MODE0_SUFFIX _primary
#define MMU_MODE1_SUFFIX _secondary
@@ -311,6 +315,7 @@ extern const VMStateDescription vmstate_s390_cpu;
#define CR0_EDAT                0x0000000000800000ULL
#define CR0_AFP                 0x0000000000040000ULL
#define CR0_VECTOR              0x0000000000020000ULL
#define CR0_IEP                 0x0000000000100000ULL
#define CR0_EMERGENCY_SIGNAL_SC 0x0000000000004000ULL
#define CR0_EXTERNAL_CALL_SC    0x0000000000002000ULL
#define CR0_CKC_SC              0x0000000000000800ULL
@@ -558,26 +563,60 @@ QEMU_BUILD_BUG_ON(sizeof(SysIB) != 4096);
#define ASCE_TYPE_SEGMENT     0x00        /* segment table type               */
#define ASCE_TABLE_LENGTH     0x03        /* region table length              */

#define REGION_ENTRY_ORIGIN   (~0xfffULL) /* region/segment table origin    */
#define REGION_ENTRY_RO       0x200       /* region/segment protection bit  */
#define REGION_ENTRY_TF       0xc0        /* region/segment table offset    */
#define REGION_ENTRY_INV      0x20        /* invalid region table entry     */
#define REGION_ENTRY_TYPE_MASK 0x0c       /* region/segment table type mask */
#define REGION_ENTRY_TYPE_R1  0x0c        /* region first table type        */
#define REGION_ENTRY_TYPE_R2  0x08        /* region second table type       */
#define REGION_ENTRY_TYPE_R3  0x04        /* region third table type        */
#define REGION_ENTRY_LENGTH   0x03        /* region third length            */

#define SEGMENT_ENTRY_ORIGIN  (~0x7ffULL) /* segment table origin        */
#define SEGMENT_ENTRY_FC      0x400       /* format control              */
#define SEGMENT_ENTRY_RO      0x200       /* page protection bit         */
#define SEGMENT_ENTRY_INV     0x20        /* invalid segment table entry */

#define VADDR_PX              0xff000     /* page index bits   */

#define PAGE_RO               0x200       /* HW read-only bit  */
#define PAGE_INVALID          0x400       /* HW invalid bit    */
#define PAGE_RES0             0x800       /* bit must be zero  */
#define REGION_ENTRY_ORIGIN         0xfffffffffffff000ULL
#define REGION_ENTRY_P              0x0000000000000200ULL
#define REGION_ENTRY_TF             0x00000000000000c0ULL
#define REGION_ENTRY_I              0x0000000000000020ULL
#define REGION_ENTRY_TT             0x000000000000000cULL
#define REGION_ENTRY_TL             0x0000000000000003ULL

#define REGION_ENTRY_TT_REGION1     0x000000000000000cULL
#define REGION_ENTRY_TT_REGION2     0x0000000000000008ULL
#define REGION_ENTRY_TT_REGION3     0x0000000000000004ULL

#define REGION3_ENTRY_RFAA          0xffffffff80000000ULL
#define REGION3_ENTRY_AV            0x0000000000010000ULL
#define REGION3_ENTRY_ACC           0x000000000000f000ULL
#define REGION3_ENTRY_F             0x0000000000000800ULL
#define REGION3_ENTRY_FC            0x0000000000000400ULL
#define REGION3_ENTRY_IEP           0x0000000000000100ULL
#define REGION3_ENTRY_CR            0x0000000000000010ULL

#define SEGMENT_ENTRY_ORIGIN        0xfffffffffffff800ULL
#define SEGMENT_ENTRY_SFAA          0xfffffffffff00000ULL
#define SEGMENT_ENTRY_AV            0x0000000000010000ULL
#define SEGMENT_ENTRY_ACC           0x000000000000f000ULL
#define SEGMENT_ENTRY_F             0x0000000000000800ULL
#define SEGMENT_ENTRY_FC            0x0000000000000400ULL
#define SEGMENT_ENTRY_P             0x0000000000000200ULL
#define SEGMENT_ENTRY_IEP           0x0000000000000100ULL
#define SEGMENT_ENTRY_I             0x0000000000000020ULL
#define SEGMENT_ENTRY_CS            0x0000000000000010ULL
#define SEGMENT_ENTRY_TT            0x000000000000000cULL

#define SEGMENT_ENTRY_TT_SEGMENT    0x0000000000000000ULL

#define PAGE_ENTRY_0                0x0000000000000800ULL
#define PAGE_ENTRY_I                0x0000000000000400ULL
#define PAGE_ENTRY_P                0x0000000000000200ULL
#define PAGE_ENTRY_IEP              0x0000000000000100ULL

#define VADDR_REGION1_TX_MASK       0xffe0000000000000ULL
#define VADDR_REGION2_TX_MASK       0x001ffc0000000000ULL
#define VADDR_REGION3_TX_MASK       0x000003ff80000000ULL
#define VADDR_SEGMENT_TX_MASK       0x000000007ff00000ULL
#define VADDR_PAGE_TX_MASK          0x00000000000ff000ULL

#define VADDR_REGION1_TX(vaddr)     (((vaddr) & VADDR_REGION1_TX_MASK) >> 53)
#define VADDR_REGION2_TX(vaddr)     (((vaddr) & VADDR_REGION2_TX_MASK) >> 42)
#define VADDR_REGION3_TX(vaddr)     (((vaddr) & VADDR_REGION3_TX_MASK) >> 31)
#define VADDR_SEGMENT_TX(vaddr)     (((vaddr) & VADDR_SEGMENT_TX_MASK) >> 20)
#define VADDR_PAGE_TX(vaddr)        (((vaddr) & VADDR_PAGE_TX_MASK) >> 12)

#define VADDR_REGION1_TL(vaddr)     (((vaddr) & 0xc000000000000000ULL) >> 62)
#define VADDR_REGION2_TL(vaddr)     (((vaddr) & 0x0018000000000000ULL) >> 51)
#define VADDR_REGION3_TL(vaddr)     (((vaddr) & 0x0000030000000000ULL) >> 40)
#define VADDR_SEGMENT_TL(vaddr)     (((vaddr) & 0x0000000060000000ULL) >> 29)

#define SK_C                    (0x1 << 1)
#define SK_R                    (0x1 << 2)
@@ -765,11 +804,8 @@ int cpu_s390x_signal_handler(int host_signum, void *pinfo, void *puc);
void s390_crw_mchk(void);
void s390_io_interrupt(uint16_t subchannel_id, uint16_t subchannel_nr,
                       uint32_t io_int_parm, uint32_t io_int_word);
/* automatically detect the instruction length */
#define ILEN_AUTO                   0xff
#define RA_IGNORED                  0
void s390_program_interrupt(CPUS390XState *env, uint32_t code, int ilen,
                            uintptr_t ra);
void s390_program_interrupt(CPUS390XState *env, uint32_t code, uintptr_t ra);
/* service interrupts are floating therefore we must not pass an cpustate */
void s390_sclp_extint(uint32_t parm);

Loading