diff options
-rw-r--r-- | hw/arm/boot.c | 5 | ||||
-rw-r--r-- | hw/intc/loongarch_extioi.c | 41 | ||||
-rw-r--r-- | hw/intc/trace-events | 3 | ||||
-rw-r--r-- | hw/loongarch/acpi-build.c | 51 | ||||
-rw-r--r-- | hw/loongarch/virt.c | 53 | ||||
-rw-r--r-- | include/hw/loongarch/virt.h | 3 | ||||
-rw-r--r-- | include/hw/pci-host/ls7a.h | 1 | ||||
-rw-r--r-- | target/arm/helper.c | 64 | ||||
-rw-r--r-- | target/arm/ptw.c | 50 | ||||
-rw-r--r-- | target/arm/sve_helper.c | 4 | ||||
-rw-r--r-- | target/loongarch/cpu.c | 10 | ||||
-rw-r--r-- | target/loongarch/cpu.h | 69 | ||||
-rw-r--r-- | target/loongarch/insn_trans/trans_farith.c.inc | 30 | ||||
-rw-r--r-- | target/loongarch/insn_trans/trans_fcmp.c.inc | 11 | ||||
-rw-r--r-- | target/loongarch/insn_trans/trans_fmemory.c.inc | 34 | ||||
-rw-r--r-- | target/loongarch/insn_trans/trans_fmov.c.inc | 29 | ||||
-rw-r--r-- | target/loongarch/insn_trans/trans_privileged.c.inc | 2 | ||||
-rw-r--r-- | target/loongarch/iocsr_helper.c | 19 | ||||
-rw-r--r-- | target/loongarch/tlb_helper.c | 5 | ||||
-rw-r--r-- | target/loongarch/translate.c | 6 |
20 files changed, 366 insertions, 124 deletions
diff --git a/hw/arm/boot.c b/hw/arm/boot.c index b106f31468..15c2bf1867 100644 --- a/hw/arm/boot.c +++ b/hw/arm/boot.c @@ -764,10 +764,15 @@ static void do_cpu_reset(void *opaque) } if (cpu_isar_feature(aa64_sve, cpu)) { env->cp15.cptr_el[3] |= R_CPTR_EL3_EZ_MASK; + env->vfp.zcr_el[3] = 0xf; } if (cpu_isar_feature(aa64_sme, cpu)) { env->cp15.cptr_el[3] |= R_CPTR_EL3_ESM_MASK; env->cp15.scr_el3 |= SCR_ENTP2; + env->vfp.smcr_el[3] = 0xf; + } + if (cpu_isar_feature(aa64_hcx, cpu)) { + env->cp15.scr_el3 |= SCR_HXEN; } /* AArch64 kernels never boot in secure mode */ assert(!info->secure_boot); diff --git a/hw/intc/loongarch_extioi.c b/hw/intc/loongarch_extioi.c index 22803969bc..4b8ec3f28a 100644 --- a/hw/intc/loongarch_extioi.c +++ b/hw/intc/loongarch_extioi.c @@ -68,44 +68,46 @@ static void extioi_setirq(void *opaque, int irq, int level) extioi_update_irq(s, irq, level); } -static uint64_t extioi_readw(void *opaque, hwaddr addr, unsigned size) +static MemTxResult extioi_readw(void *opaque, hwaddr addr, uint64_t *data, + unsigned size, MemTxAttrs attrs) { LoongArchExtIOI *s = LOONGARCH_EXTIOI(opaque); unsigned long offset = addr & 0xffff; - uint32_t index, cpu, ret = 0; + uint32_t index, cpu; switch (offset) { case EXTIOI_NODETYPE_START ... EXTIOI_NODETYPE_END - 1: index = (offset - EXTIOI_NODETYPE_START) >> 2; - ret = s->nodetype[index]; + *data = s->nodetype[index]; break; case EXTIOI_IPMAP_START ... EXTIOI_IPMAP_END - 1: index = (offset - EXTIOI_IPMAP_START) >> 2; - ret = s->ipmap[index]; + *data = s->ipmap[index]; break; case EXTIOI_ENABLE_START ... EXTIOI_ENABLE_END - 1: index = (offset - EXTIOI_ENABLE_START) >> 2; - ret = s->enable[index]; + *data = s->enable[index]; break; case EXTIOI_BOUNCE_START ... EXTIOI_BOUNCE_END - 1: index = (offset - EXTIOI_BOUNCE_START) >> 2; - ret = s->bounce[index]; + *data = s->bounce[index]; break; case EXTIOI_COREISR_START ... EXTIOI_COREISR_END - 1: - index = ((offset - EXTIOI_COREISR_START) & 0x1f) >> 2; - cpu = ((offset - EXTIOI_COREISR_START) >> 8) & 0x3; - ret = s->coreisr[cpu][index]; + index = (offset - EXTIOI_COREISR_START) >> 2; + /* using attrs to get current cpu index */ + cpu = attrs.requester_id; + *data = s->coreisr[cpu][index]; break; case EXTIOI_COREMAP_START ... EXTIOI_COREMAP_END - 1: index = (offset - EXTIOI_COREMAP_START) >> 2; - ret = s->coremap[index]; + *data = s->coremap[index]; break; default: break; } - trace_loongarch_extioi_readw(addr, ret); - return ret; + trace_loongarch_extioi_readw(addr, *data); + return MEMTX_OK; } static inline void extioi_enable_irq(LoongArchExtIOI *s, int index,\ @@ -127,8 +129,9 @@ static inline void extioi_enable_irq(LoongArchExtIOI *s, int index,\ } } -static void extioi_writew(void *opaque, hwaddr addr, - uint64_t val, unsigned size) +static MemTxResult extioi_writew(void *opaque, hwaddr addr, + uint64_t val, unsigned size, + MemTxAttrs attrs) { LoongArchExtIOI *s = LOONGARCH_EXTIOI(opaque); int i, cpu, index, old_data, irq; @@ -183,8 +186,9 @@ static void extioi_writew(void *opaque, hwaddr addr, s->bounce[index] = val; break; case EXTIOI_COREISR_START ... EXTIOI_COREISR_END - 1: - index = ((offset - EXTIOI_COREISR_START) & 0x1f) >> 2; - cpu = ((offset - EXTIOI_COREISR_START) >> 8) & 0x3; + index = (offset - EXTIOI_COREISR_START) >> 2; + /* using attrs to get current cpu index */ + cpu = attrs.requester_id; old_data = s->coreisr[cpu][index]; s->coreisr[cpu][index] = old_data & ~val; /* write 1 to clear interrrupt */ @@ -231,11 +235,12 @@ static void extioi_writew(void *opaque, hwaddr addr, default: break; } + return MEMTX_OK; } static const MemoryRegionOps extioi_ops = { - .read = extioi_readw, - .write = extioi_writew, + .read_with_attrs = extioi_readw, + .write_with_attrs = extioi_writew, .impl.min_access_size = 4, .impl.max_access_size = 4, .valid.min_access_size = 4, diff --git a/hw/intc/trace-events b/hw/intc/trace-events index 0a90c1cdec..6fbc2045e6 100644 --- a/hw/intc/trace-events +++ b/hw/intc/trace-events @@ -306,6 +306,5 @@ loongarch_msi_set_irq(int irq_num) "set msi irq %d" # loongarch_extioi.c loongarch_extioi_setirq(int irq, int level) "set extirq irq %d level %d" -loongarch_extioi_readw(uint64_t addr, uint32_t val) "addr: 0x%"PRIx64 "val: 0x%x" +loongarch_extioi_readw(uint64_t addr, uint64_t val) "addr: 0x%"PRIx64 "val: 0x%" PRIx64 loongarch_extioi_writew(uint64_t addr, uint64_t val) "addr: 0x%"PRIx64 "val: 0x%" PRIx64 - diff --git a/hw/loongarch/acpi-build.c b/hw/loongarch/acpi-build.c index 378a6d9d38..68dfb9f88a 100644 --- a/hw/loongarch/acpi-build.c +++ b/hw/loongarch/acpi-build.c @@ -31,6 +31,9 @@ #include "hw/acpi/generic_event_device.h" #include "hw/pci-host/gpex.h" +#include "sysemu/tpm.h" +#include "hw/platform-bus.h" +#include "hw/acpi/aml-build.h" #define ACPI_BUILD_ALIGN_SIZE 0x1000 #define ACPI_BUILD_TABLE_SIZE 0x20000 @@ -275,6 +278,41 @@ static void build_pci_device_aml(Aml *scope, LoongArchMachineState *lams) acpi_dsdt_add_gpex(scope, &cfg); } +#ifdef CONFIG_TPM +static void acpi_dsdt_add_tpm(Aml *scope, LoongArchMachineState *vms) +{ + PlatformBusDevice *pbus = PLATFORM_BUS_DEVICE(vms->platform_bus_dev); + hwaddr pbus_base = VIRT_PLATFORM_BUS_BASEADDRESS; + SysBusDevice *sbdev = SYS_BUS_DEVICE(tpm_find()); + MemoryRegion *sbdev_mr; + hwaddr tpm_base; + + if (!sbdev) { + return; + } + + tpm_base = platform_bus_get_mmio_addr(pbus, sbdev, 0); + assert(tpm_base != -1); + + tpm_base += pbus_base; + + sbdev_mr = sysbus_mmio_get_region(sbdev, 0); + + Aml *dev = aml_device("TPM0"); + aml_append(dev, aml_name_decl("_HID", aml_string("MSFT0101"))); + aml_append(dev, aml_name_decl("_STR", aml_string("TPM 2.0 Device"))); + aml_append(dev, aml_name_decl("_UID", aml_int(0))); + + Aml *crs = aml_resource_template(); + aml_append(crs, + aml_memory32_fixed(tpm_base, + (uint32_t)memory_region_size(sbdev_mr), + AML_READ_WRITE)); + aml_append(dev, aml_name_decl("_CRS", crs)); + aml_append(scope, dev); +} +#endif + /* build DSDT */ static void build_dsdt(GArray *table_data, BIOSLinker *linker, MachineState *machine) @@ -289,7 +327,9 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, MachineState *machine) build_uart_device_aml(dsdt); build_pci_device_aml(dsdt, lams); build_la_ged_aml(dsdt, machine); - +#ifdef CONFIG_TPM + acpi_dsdt_add_tpm(dsdt, lams); +#endif /* System State Package */ scope = aml_scope("\\"); pkg = aml_package(4); @@ -359,6 +399,15 @@ static void acpi_build(AcpiBuildTables *tables, MachineState *machine) lams->oem_table_id); } +#ifdef CONFIG_TPM + /* TPM info */ + if (tpm_get_version(tpm_find()) == TPM_VERSION_2_0) { + acpi_add_table(table_offsets, tables_blob); + build_tpm2(tables_blob, tables->linker, + tables->tcpalog, lams->oem_id, + lams->oem_table_id); + } +#endif /* Add tables supplied by user (if any) */ for (u = acpi_table_first(); u; u = acpi_table_next(u)) { unsigned len = acpi_table_len(u); diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c index 4b595a9ea4..5e4c2790bf 100644 --- a/hw/loongarch/virt.c +++ b/hw/loongarch/virt.c @@ -41,6 +41,36 @@ #include "hw/platform-bus.h" #include "hw/display/ramfb.h" #include "hw/mem/pc-dimm.h" +#include "sysemu/tpm.h" + +static void fdt_add_rtc_node(LoongArchMachineState *lams) +{ + char *nodename; + hwaddr base = VIRT_RTC_REG_BASE; + hwaddr size = VIRT_RTC_LEN; + MachineState *ms = MACHINE(lams); + + nodename = g_strdup_printf("/rtc@%" PRIx64, base); + qemu_fdt_add_subnode(ms->fdt, nodename); + qemu_fdt_setprop_string(ms->fdt, nodename, "compatible", "loongson,ls7a-rtc"); + qemu_fdt_setprop_sized_cells(ms->fdt, nodename, "reg", 0x0, base, size); + g_free(nodename); +} + +static void fdt_add_uart_node(LoongArchMachineState *lams) +{ + char *nodename; + hwaddr base = VIRT_UART_BASE; + hwaddr size = VIRT_UART_SIZE; + MachineState *ms = MACHINE(lams); + + nodename = g_strdup_printf("/serial@%" PRIx64, base); + qemu_fdt_add_subnode(ms->fdt, nodename); + qemu_fdt_setprop_string(ms->fdt, nodename, "compatible", "ns16550a"); + qemu_fdt_setprop_cells(ms->fdt, nodename, "reg", 0x0, base, 0x0, size); + qemu_fdt_setprop_cell(ms->fdt, nodename, "clock-frequency", 100000000); + g_free(nodename); +} static void create_fdt(LoongArchMachineState *lams) { @@ -159,7 +189,6 @@ static void fdt_add_pcie_node(const LoongArchMachineState *lams) 1, FDT_PCI_RANGE_MMIO, 2, base_mmio, 2, base_mmio, 2, size_mmio); g_free(nodename); - qemu_fdt_dumpdtb(ms->fdt, lams->fdt_size); } static void fdt_add_irqchip_node(LoongArchMachineState *lams) @@ -423,6 +452,7 @@ static void loongarch_devices_init(DeviceState *pch_pic, LoongArchMachineState * qdev_get_gpio_in(pch_pic, VIRT_UART_IRQ - PCH_PIC_IRQ_OFFSET), 115200, serial_hd(0), DEVICE_LITTLE_ENDIAN); + fdt_add_uart_node(lams); /* Network init */ for (i = 0; i < nb_nics; i++) { @@ -443,6 +473,7 @@ static void loongarch_devices_init(DeviceState *pch_pic, LoongArchMachineState * sysbus_create_simple("ls7a_rtc", VIRT_RTC_REG_BASE, qdev_get_gpio_in(pch_pic, VIRT_RTC_IRQ - PCH_PIC_IRQ_OFFSET)); + fdt_add_rtc_node(lams); pm_mem = g_new(MemoryRegion, 1); memory_region_init_io(pm_mem, NULL, &loongarch_virt_pm_ops, @@ -656,6 +687,7 @@ static void loongarch_init(MachineState *machine) MemoryRegion *address_space_mem = get_system_memory(); LoongArchMachineState *lams = LOONGARCH_MACHINE(machine); int i; + hwaddr fdt_base; if (!cpu_model) { cpu_model = LOONGARCH_CPU_TYPE_NAME("la464"); @@ -760,12 +792,16 @@ static void loongarch_init(MachineState *machine) lams->machine_done.notify = virt_machine_done; qemu_add_machine_init_done_notifier(&lams->machine_done); fdt_add_pcie_node(lams); - - /* load fdt */ - MemoryRegion *fdt_rom = g_new(MemoryRegion, 1); - memory_region_init_rom(fdt_rom, NULL, "fdt", VIRT_FDT_SIZE, &error_fatal); - memory_region_add_subregion(get_system_memory(), VIRT_FDT_BASE, fdt_rom); - rom_add_blob_fixed("fdt", machine->fdt, lams->fdt_size, VIRT_FDT_BASE); + /* + * Since lowmem region starts from 0, FDT base address is located + * at 2 MiB to avoid NULL pointer access. + * + * Put the FDT into the memory map as a ROM image: this will ensure + * the FDT is copied again upon reset, even if addr points into RAM. + */ + fdt_base = 2 * MiB; + qemu_fdt_dumpdtb(machine->fdt, lams->fdt_size); + rom_add_blob_fixed("fdt", machine->fdt, lams->fdt_size, fdt_base); } bool loongarch_is_acpi_enabled(LoongArchMachineState *lams) @@ -925,6 +961,9 @@ static void loongarch_class_init(ObjectClass *oc, void *data) object_class_property_set_description(oc, "acpi", "Enable ACPI"); machine_class_allow_dynamic_sysbus_dev(mc, TYPE_RAMFB_DEVICE); +#ifdef CONFIG_TPM + machine_class_allow_dynamic_sysbus_dev(mc, TYPE_TPM_TIS_SYSBUS); +#endif } static const TypeInfo loongarch_machine_types[] = { diff --git a/include/hw/loongarch/virt.h b/include/hw/loongarch/virt.h index 09f1c88ee5..45c383f5a7 100644 --- a/include/hw/loongarch/virt.h +++ b/include/hw/loongarch/virt.h @@ -28,9 +28,6 @@ #define VIRT_GED_MEM_ADDR (VIRT_GED_EVT_ADDR + ACPI_GED_EVT_SEL_LEN) #define VIRT_GED_REG_ADDR (VIRT_GED_MEM_ADDR + MEMORY_HOTPLUG_IO_LEN) -#define VIRT_FDT_BASE 0x1c400000 -#define VIRT_FDT_SIZE 0x100000 - struct LoongArchMachineState { /*< private >*/ MachineState parent_obj; diff --git a/include/hw/pci-host/ls7a.h b/include/hw/pci-host/ls7a.h index 9bd875ca8b..df7fa55a30 100644 --- a/include/hw/pci-host/ls7a.h +++ b/include/hw/pci-host/ls7a.h @@ -37,6 +37,7 @@ #define VIRT_PCI_IRQS 48 #define VIRT_UART_IRQ (PCH_PIC_IRQ_OFFSET + 2) #define VIRT_UART_BASE 0x1fe001e0 +#define VIRT_UART_SIZE 0X100 #define VIRT_RTC_IRQ (PCH_PIC_IRQ_OFFSET + 3) #define VIRT_MISC_REG_BASE (VIRT_PCH_REG_BASE + 0x00080000) #define VIRT_RTC_REG_BASE (VIRT_MISC_REG_BASE + 0x00050100) diff --git a/target/arm/helper.c b/target/arm/helper.c index b070a20f1a..d8c8223ec3 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -3501,19 +3501,22 @@ static void ats_write64(CPUARMState *env, const ARMCPRegInfo *ri, MMUAccessType access_type = ri->opc2 & 1 ? MMU_DATA_STORE : MMU_DATA_LOAD; ARMMMUIdx mmu_idx; int secure = arm_is_secure_below_el3(env); + uint64_t hcr_el2 = arm_hcr_el2_eff(env); + bool regime_e20 = (hcr_el2 & (HCR_E2H | HCR_TGE)) == (HCR_E2H | HCR_TGE); switch (ri->opc2 & 6) { case 0: switch (ri->opc1) { case 0: /* AT S1E1R, AT S1E1W, AT S1E1RP, AT S1E1WP */ if (ri->crm == 9 && (env->pstate & PSTATE_PAN)) { - mmu_idx = ARMMMUIdx_Stage1_E1_PAN; + mmu_idx = regime_e20 ? + ARMMMUIdx_E20_2_PAN : ARMMMUIdx_Stage1_E1_PAN; } else { - mmu_idx = ARMMMUIdx_Stage1_E1; + mmu_idx = regime_e20 ? ARMMMUIdx_E20_2 : ARMMMUIdx_Stage1_E1; } break; case 4: /* AT S1E2R, AT S1E2W */ - mmu_idx = ARMMMUIdx_E2; + mmu_idx = hcr_el2 & HCR_E2H ? ARMMMUIdx_E20_2 : ARMMMUIdx_E2; break; case 6: /* AT S1E3R, AT S1E3W */ mmu_idx = ARMMMUIdx_E3; @@ -3524,13 +3527,13 @@ static void ats_write64(CPUARMState *env, const ARMCPRegInfo *ri, } break; case 2: /* AT S1E0R, AT S1E0W */ - mmu_idx = ARMMMUIdx_Stage1_E0; + mmu_idx = regime_e20 ? ARMMMUIdx_E20_0 : ARMMMUIdx_Stage1_E0; break; case 4: /* AT S12E1R, AT S12E1W */ - mmu_idx = ARMMMUIdx_E10_1; + mmu_idx = regime_e20 ? ARMMMUIdx_E20_2 : ARMMMUIdx_E10_1; break; case 6: /* AT S12E0R, AT S12E0W */ - mmu_idx = ARMMMUIdx_E10_0; + mmu_idx = regime_e20 ? ARMMMUIdx_E20_0 : ARMMMUIdx_E10_0; break; default: g_assert_not_reached(); @@ -6717,51 +6720,51 @@ static const ARMCPRegInfo pauth_reginfo[] = { static const ARMCPRegInfo tlbirange_reginfo[] = { { .name = "TLBI_RVAE1IS", .state = ARM_CP_STATE_AA64, .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 2, .opc2 = 1, - .access = PL1_W, .type = ARM_CP_NO_RAW, + .access = PL1_W, .accessfn = access_ttlb, .type = ARM_CP_NO_RAW, .writefn = tlbi_aa64_rvae1is_write }, { .name = "TLBI_RVAAE1IS", .state = ARM_CP_STATE_AA64, .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 2, .opc2 = 3, - .access = PL1_W, .type = ARM_CP_NO_RAW, + .access = PL1_W, .accessfn = access_ttlb, .type = ARM_CP_NO_RAW, .writefn = tlbi_aa64_rvae1is_write }, { .name = "TLBI_RVALE1IS", .state = ARM_CP_STATE_AA64, .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 2, .opc2 = 5, - .access = PL1_W, .type = ARM_CP_NO_RAW, + .access = PL1_W, .accessfn = access_ttlb, .type = ARM_CP_NO_RAW, .writefn = tlbi_aa64_rvae1is_write }, { .name = "TLBI_RVAALE1IS", .state = ARM_CP_STATE_AA64, .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 2, .opc2 = 7, - .access = PL1_W, .type = ARM_CP_NO_RAW, + .access = PL1_W, .accessfn = access_ttlb, .type = ARM_CP_NO_RAW, .writefn = tlbi_aa64_rvae1is_write }, { .name = "TLBI_RVAE1OS", .state = ARM_CP_STATE_AA64, .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 5, .opc2 = 1, - .access = PL1_W, .type = ARM_CP_NO_RAW, + .access = PL1_W, .accessfn = access_ttlb, .type = ARM_CP_NO_RAW, .writefn = tlbi_aa64_rvae1is_write }, { .name = "TLBI_RVAAE1OS", .state = ARM_CP_STATE_AA64, .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 5, .opc2 = 3, - .access = PL1_W, .type = ARM_CP_NO_RAW, + .access = PL1_W, .accessfn = access_ttlb, .type = ARM_CP_NO_RAW, .writefn = tlbi_aa64_rvae1is_write }, { .name = "TLBI_RVALE1OS", .state = ARM_CP_STATE_AA64, .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 5, .opc2 = 5, - .access = PL1_W, .type = ARM_CP_NO_RAW, + .access = PL1_W, .accessfn = access_ttlb, .type = ARM_CP_NO_RAW, .writefn = tlbi_aa64_rvae1is_write }, { .name = "TLBI_RVAALE1OS", .state = ARM_CP_STATE_AA64, .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 5, .opc2 = 7, - .access = PL1_W, .type = ARM_CP_NO_RAW, + .access = PL1_W, .accessfn = access_ttlb, .type = ARM_CP_NO_RAW, .writefn = tlbi_aa64_rvae1is_write }, { .name = "TLBI_RVAE1", .state = ARM_CP_STATE_AA64, .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 6, .opc2 = 1, - .access = PL1_W, .type = ARM_CP_NO_RAW, + .access = PL1_W, .accessfn = access_ttlb, .type = ARM_CP_NO_RAW, .writefn = tlbi_aa64_rvae1_write }, { .name = "TLBI_RVAAE1", .state = ARM_CP_STATE_AA64, .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 6, .opc2 = 3, - .access = PL1_W, .type = ARM_CP_NO_RAW, + .access = PL1_W, .accessfn = access_ttlb, .type = ARM_CP_NO_RAW, .writefn = tlbi_aa64_rvae1_write }, { .name = "TLBI_RVALE1", .state = ARM_CP_STATE_AA64, .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 6, .opc2 = 5, - .access = PL1_W, .type = ARM_CP_NO_RAW, + .access = PL1_W, .accessfn = access_ttlb, .type = ARM_CP_NO_RAW, .writefn = tlbi_aa64_rvae1_write }, { .name = "TLBI_RVAALE1", .state = ARM_CP_STATE_AA64, .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 6, .opc2 = 7, - .access = PL1_W, .type = ARM_CP_NO_RAW, + .access = PL1_W, .accessfn = access_ttlb, .type = ARM_CP_NO_RAW, .writefn = tlbi_aa64_rvae1_write }, { .name = "TLBI_RIPAS2E1IS", .state = ARM_CP_STATE_AA64, .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 0, .opc2 = 2, @@ -6832,27 +6835,27 @@ static const ARMCPRegInfo tlbirange_reginfo[] = { static const ARMCPRegInfo tlbios_reginfo[] = { { .name = "TLBI_VMALLE1OS", .state = ARM_CP_STATE_AA64, .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 1, .opc2 = 0, - .access = PL1_W, .type = ARM_CP_NO_RAW, + .access = PL1_W, .accessfn = access_ttlb, .type = ARM_CP_NO_RAW, .writefn = tlbi_aa64_vmalle1is_write }, { .name = "TLBI_VAE1OS", .state = ARM_CP_STATE_AA64, .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 1, .opc2 = 1, - .access = PL1_W, .type = ARM_CP_NO_RAW, + .access = PL1_W, .accessfn = access_ttlb, .type = ARM_CP_NO_RAW, .writefn = tlbi_aa64_vae1is_write }, { .name = "TLBI_ASIDE1OS", .state = ARM_CP_STATE_AA64, .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 1, .opc2 = 2, - .access = PL1_W, .type = ARM_CP_NO_RAW, + .access = PL1_W, .accessfn = access_ttlb, .type = ARM_CP_NO_RAW, .writefn = tlbi_aa64_vmalle1is_write }, { .name = "TLBI_VAAE1OS", .state = ARM_CP_STATE_AA64, .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 1, .opc2 = 3, - .access = PL1_W, .type = ARM_CP_NO_RAW, + .access = PL1_W, .accessfn = access_ttlb, .type = ARM_CP_NO_RAW, .writefn = tlbi_aa64_vae1is_write }, { .name = "TLBI_VALE1OS", .state = ARM_CP_STATE_AA64, .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 1, .opc2 = 5, - .access = PL1_W, .type = ARM_CP_NO_RAW, + .access = PL1_W, .accessfn = access_ttlb, .type = ARM_CP_NO_RAW, .writefn = tlbi_aa64_vae1is_write }, { .name = "TLBI_VAALE1OS", .state = ARM_CP_STATE_AA64, .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 1, .opc2 = 7, - .access = PL1_W, .type = ARM_CP_NO_RAW, + .access = PL1_W, .accessfn = access_ttlb, .type = ARM_CP_NO_RAW, .writefn = tlbi_aa64_vae1is_write }, { .name = "TLBI_ALLE2OS", .state = ARM_CP_STATE_AA64, .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 1, .opc2 = 0, @@ -11003,6 +11006,15 @@ ARMMMUIdx arm_v7m_mmu_idx_for_secstate(CPUARMState *env, bool secstate) } #endif +static bool arm_pan_enabled(CPUARMState *env) +{ + if (is_a64(env)) { + return env->pstate & PSTATE_PAN; + } else { + return env->uncached_cpsr & CPSR_PAN; + } +} + ARMMMUIdx arm_mmu_idx_el(CPUARMState *env, int el) { ARMMMUIdx idx; @@ -11023,7 +11035,7 @@ ARMMMUIdx arm_mmu_idx_el(CPUARMState *env, int el) } break; case 1: - if (env->pstate & PSTATE_PAN) { + if (arm_pan_enabled(env)) { idx = ARMMMUIdx_E10_1_PAN; } else { idx = ARMMMUIdx_E10_1; @@ -11032,7 +11044,7 @@ ARMMMUIdx arm_mmu_idx_el(CPUARMState *env, int el) case 2: /* Note that TGE does not apply at EL2. */ if (arm_hcr_el2_eff(env) & HCR_E2H) { - if (env->pstate & PSTATE_PAN) { + if (arm_pan_enabled(env)) { idx = ARMMMUIdx_E20_2_PAN; } else { idx = ARMMMUIdx_E20_2; diff --git a/target/arm/ptw.c b/target/arm/ptw.c index 58a7bbda50..3745ac9723 100644 --- a/target/arm/ptw.c +++ b/target/arm/ptw.c @@ -503,12 +503,11 @@ static bool get_level1_table_address(CPUARMState *env, ARMMMUIdx mmu_idx, * @mmu_idx: MMU index indicating required translation regime * @ap: The 3-bit access permissions (AP[2:0]) * @domain_prot: The 2-bit domain access permissions + * @is_user: TRUE if accessing from PL0 */ -static int ap_to_rw_prot(CPUARMState *env, ARMMMUIdx mmu_idx, - int ap, int domain_prot) +static int ap_to_rw_prot_is_user(CPUARMState *env, ARMMMUIdx mmu_idx, + int ap, int domain_prot, bool is_user) { - bool is_user = regime_is_user(env, mmu_idx); - if (domain_prot == 3) { return PAGE_READ | PAGE_WRITE; } @@ -553,6 +552,20 @@ static int ap_to_rw_prot(CPUARMState *env, ARMMMUIdx mmu_idx, } /* + * Translate section/page access permissions to page R/W protection flags + * @env: CPUARMState + * @mmu_idx: MMU index indicating required translation regime + * @ap: The 3-bit access permissions (AP[2:0]) + * @domain_prot: The 2-bit domain access permissions + */ +static int ap_to_rw_prot(CPUARMState *env, ARMMMUIdx mmu_idx, + int ap, int domain_prot) +{ + return ap_to_rw_prot_is_user(env, mmu_idx, ap, domain_prot, + regime_is_user(env, mmu_idx)); +} + +/* * Translate section/page access permissions to page R/W protection flags. * @ap: The 2-bit simple AP (AP[2:1]) * @is_user: TRUE if accessing from PL0 @@ -720,6 +733,7 @@ static bool get_phys_addr_v6(CPUARMState *env, S1Translate *ptw, hwaddr phys_addr; uint32_t dacr; bool ns; + int user_prot; /* Pagetable walk. */ /* Lookup l1 descriptor. */ @@ -831,8 +845,10 @@ static bool get_phys_addr_v6(CPUARMState *env, S1Translate *ptw, goto do_fault; } result->f.prot = simple_ap_to_rw_prot(env, mmu_idx, ap >> 1); + user_prot = simple_ap_to_rw_prot_is_user(ap >> 1, 1); } else { result->f.prot = ap_to_rw_prot(env, mmu_idx, ap, domain_prot); + user_prot = ap_to_rw_prot_is_user(env, mmu_idx, ap, domain_prot, 1); } if (result->f.prot && !xn) { result->f.prot |= PAGE_EXEC; @@ -842,6 +858,14 @@ static bool get_phys_addr_v6(CPUARMState *env, S1Translate *ptw, fi->type = ARMFault_Permission; goto do_fault; } + if (regime_is_pan(env, mmu_idx) && + !regime_is_user(env, mmu_idx) && + user_prot && + access_type != MMU_INST_FETCH) { + /* Privileged Access Never fault */ + fi->type = ARMFault_Permission; + goto do_fault; + } } if (ns) { /* The NS bit will (as required by the architecture) have no effect if @@ -1357,7 +1381,7 @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw, descaddr |= (address >> (stride * (4 - level))) & indexmask; descaddr &= ~7ULL; nstable = extract32(tableattrs, 4, 1); - if (!nstable) { + if (nstable) { /* * Stage2_S -> Stage2 or Phys_S -> Phys_NS * Assert that the non-secure idx are even, and relative order. @@ -2671,6 +2695,13 @@ static bool get_phys_addr_with_struct(CPUARMState *env, S1Translate *ptw, bool is_secure = ptw->in_secure; ARMMMUIdx s1_mmu_idx; + /* + * The page table entries may downgrade secure to non-secure, but + * cannot upgrade an non-secure translation regime's attributes + * to secure. + */ + result->f.attrs.secure = is_secure; + switch (mmu_idx) { case ARMMMUIdx_Phys_S: case ARMMMUIdx_Phys_NS: @@ -2712,12 +2743,6 @@ static bool get_phys_addr_with_struct(CPUARMState *env, S1Translate *ptw, break; } - /* - * The page table entries may downgrade secure to non-secure, but - * cannot upgrade an non-secure translation regime's attributes - * to secure. - */ - result->f.attrs.secure = is_secure; result->f.attrs.user = regime_is_user(env, mmu_idx); /* @@ -2773,7 +2798,8 @@ static bool get_phys_addr_with_struct(CPUARMState *env, S1Translate *ptw, if (regime_using_lpae_format(env, mmu_idx)) { return get_phys_addr_lpae(env, ptw, address, access_type, false, result, fi); - } else if (regime_sctlr(env, mmu_idx) & SCTLR_XP) { + } else if (arm_feature(env, ARM_FEATURE_V7) || + regime_sctlr(env, mmu_idx) & SCTLR_XP) { return get_phys_addr_v6(env, ptw, address, access_type, result, fi); } else { return get_phys_addr_v5(env, ptw, address, access_type, result, fi); diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c index 3d0d2987cd..1afeadf9c8 100644 --- a/target/arm/sve_helper.c +++ b/target/arm/sve_helper.c @@ -3366,10 +3366,10 @@ void HELPER(NAME)(void *vd, void *vn, void *vm, uint32_t desc) \ /* We produce output faster than we consume input. \ Therefore we must be mindful of possible overlap. */ \ if (unlikely((vn - vd) < (uintptr_t)oprsz)) { \ - vn = memcpy(&tmp_n, vn, oprsz_2); \ + vn = memcpy(&tmp_n, vn, oprsz); \ } \ if (unlikely((vm - vd) < (uintptr_t)oprsz)) { \ - vm = memcpy(&tmp_m, vm, oprsz_2); \ + vm = memcpy(&tmp_m, vm, oprsz); \ } \ for (i = 0; i < oprsz_2; i += sizeof(TYPE)) { \ *(TYPE *)(vd + H(2 * i + 0)) = *(TYPE *)(vn + odd_ofs + H(i)); \ diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c index 49393d95d8..46b04cbdad 100644 --- a/target/loongarch/cpu.c +++ b/target/loongarch/cpu.c @@ -48,6 +48,7 @@ static const char * const excp_names[] = { [EXCCODE_BRK] = "Break", [EXCCODE_INE] = "Instruction Non-Existent", [EXCCODE_IPE] = "Instruction privilege error", + [EXCCODE_FPD] = "Floating Point Disabled", [EXCCODE_FPE] = "Floating Point Exception", [EXCCODE_DBP] = "Debug breakpoint", [EXCCODE_BCE] = "Bound Check Exception", @@ -177,6 +178,7 @@ static void loongarch_cpu_do_interrupt(CPUState *cs) } QEMU_FALLTHROUGH; case EXCCODE_PIF: + case EXCCODE_ADEF: cause = cs->exception_index; update_badinstr = 0; break; @@ -184,6 +186,7 @@ static void loongarch_cpu_do_interrupt(CPUState *cs) case EXCCODE_BRK: case EXCCODE_INE: case EXCCODE_IPE: + case EXCCODE_FPD: case EXCCODE_FPE: case EXCCODE_BCE: env->CSR_BADV = env->pc; @@ -220,7 +223,10 @@ static void loongarch_cpu_do_interrupt(CPUState *cs) env->CSR_TLBRERA = FIELD_DP64(env->CSR_TLBRERA, CSR_TLBRERA, PC, (env->pc >> 2)); } else { - env->CSR_ESTAT = FIELD_DP64(env->CSR_ESTAT, CSR_ESTAT, ECODE, cause); + env->CSR_ESTAT = FIELD_DP64(env->CSR_ESTAT, CSR_ESTAT, ECODE, + EXCODE_MCODE(cause)); + env->CSR_ESTAT = FIELD_DP64(env->CSR_ESTAT, CSR_ESTAT, ESUBCODE, + EXCODE_SUBCODE(cause)); env->CSR_PRMD = FIELD_DP64(env->CSR_PRMD, CSR_PRMD, PPLV, FIELD_EX64(env->CSR_CRMD, CSR_CRMD, PLV)); env->CSR_PRMD = FIELD_DP64(env->CSR_PRMD, CSR_PRMD, PIE, @@ -257,7 +263,7 @@ static void loongarch_cpu_do_interrupt(CPUState *cs) env->pc = env->CSR_TLBRENTRY; } else { env->pc = env->CSR_EENTRY; - env->pc += cause * vec_size; + env->pc += EXCODE_MCODE(cause) * vec_size; } qemu_log_mask(CPU_LOG_INT, "%s: PC " TARGET_FMT_lx " ERA " TARGET_FMT_lx diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h index dce999aaac..08c1f6baa1 100644 --- a/target/loongarch/cpu.h +++ b/target/loongarch/cpu.h @@ -14,6 +14,7 @@ #include "qemu/timer.h" #include "exec/memory.h" #include "hw/sysbus.h" +#include "cpu-csr.h" #define IOCSRF_TEMP 0 #define IOCSRF_NODECNT 1 @@ -75,33 +76,37 @@ FIELD(FCSR0, CAUSE, 24, 5) #define FP_DIV0 8 #define FP_INVALID 16 -#define EXCCODE_EXTERNAL_INT 64 /* plus external interrupt number */ -#define EXCCODE_INT 0 -#define EXCCODE_PIL 1 -#define EXCCODE_PIS 2 -#define EXCCODE_PIF 3 -#define EXCCODE_PME 4 -#define EXCCODE_PNR 5 -#define EXCCODE_PNX 6 -#define EXCCODE_PPI 7 -#define EXCCODE_ADEF 8 /* Different exception subcode */ -#define EXCCODE_ADEM 8 -#define EXCCODE_ALE 9 -#define EXCCODE_BCE 10 -#define EXCCODE_SYS 11 -#define EXCCODE_BRK 12 -#define EXCCODE_INE 13 -#define EXCCODE_IPE 14 -#define EXCCODE_FPD 15 -#define EXCCODE_SXD 16 -#define EXCCODE_ASXD 17 -#define EXCCODE_FPE 18 /* Different exception subcode */ -#define EXCCODE_VFPE 18 -#define EXCCODE_WPEF 19 /* Different exception subcode */ -#define EXCCODE_WPEM 19 -#define EXCCODE_BTD 20 -#define EXCCODE_BTE 21 -#define EXCCODE_DBP 26 /* Reserved subcode used for debug */ +#define EXCODE(code, subcode) ( ((subcode) << 6) | (code) ) +#define EXCODE_MCODE(code) ( (code) & 0x3f ) +#define EXCODE_SUBCODE(code) ( (code) >> 6 ) + +#define EXCCODE_EXTERNAL_INT 64 /* plus external interrupt number */ +#define EXCCODE_INT EXCODE(0, 0) +#define EXCCODE_PIL EXCODE(1, 0) +#define EXCCODE_PIS EXCODE(2, 0) +#define EXCCODE_PIF EXCODE(3, 0) +#define EXCCODE_PME EXCODE(4, 0) +#define EXCCODE_PNR EXCODE(5, 0) +#define EXCCODE_PNX EXCODE(6, 0) +#define EXCCODE_PPI EXCODE(7, 0) +#define EXCCODE_ADEF EXCODE(8, 0) /* Different exception subcode */ +#define EXCCODE_ADEM EXCODE(8, 1) +#define EXCCODE_ALE EXCODE(9, 0) +#define EXCCODE_BCE EXCODE(10, 0) +#define EXCCODE_SYS EXCODE(11, 0) +#define EXCCODE_BRK EXCODE(12, 0) +#define EXCCODE_INE EXCODE(13, 0) +#define EXCCODE_IPE EXCODE(14, 0) +#define EXCCODE_FPD EXCODE(15, 0) +#define EXCCODE_SXD EXCODE(16, 0) +#define EXCCODE_ASXD EXCODE(17, 0) +#define EXCCODE_FPE EXCODE(18, 0) /* Different exception subcode */ +#define EXCCODE_VFPE EXCODE(18, 1) +#define EXCCODE_WPEF EXCODE(19, 0) /* Different exception subcode */ +#define EXCCODE_WPEM EXCODE(19, 1) +#define EXCCODE_BTD EXCODE(20, 0) +#define EXCCODE_BTE EXCODE(21, 0) +#define EXCCODE_DBP EXCODE(26, 0) /* Reserved subcode used for debug */ /* cpucfg[0] bits */ FIELD(CPUCFG0, PRID, 0, 32) @@ -387,6 +392,13 @@ static inline int cpu_mmu_index(CPULoongArchState *env, bool ifetch) #endif } +/* + * LoongArch CPUs hardware flags. + */ +#define HW_FLAGS_PLV_MASK R_CSR_CRMD_PLV_MASK /* 0x03 */ +#define HW_FLAGS_CRMD_PG R_CSR_CRMD_PG_MASK /* 0x10 */ +#define HW_FLAGS_EUEN_FPE 0x04 + static inline void cpu_get_tb_cpu_state(CPULoongArchState *env, target_ulong *pc, target_ulong *cs_base, @@ -394,7 +406,8 @@ static inline void cpu_get_tb_cpu_state(CPULoongArchState *env, { *pc = env->pc; *cs_base = 0; - *flags = cpu_mmu_index(env, false); + *flags = env->CSR_CRMD & (R_CSR_CRMD_PLV_MASK | R_CSR_CRMD_PG_MASK); + *flags |= FIELD_EX64(env->CSR_EUEN, CSR_EUEN, FPE) * HW_FLAGS_EUEN_FPE; } void loongarch_cpu_list(void); diff --git a/target/loongarch/insn_trans/trans_farith.c.inc b/target/loongarch/insn_trans/trans_farith.c.inc index 7bb3f41aee..e2dec75dfb 100644 --- a/target/loongarch/insn_trans/trans_farith.c.inc +++ b/target/loongarch/insn_trans/trans_farith.c.inc @@ -3,9 +3,22 @@ * Copyright (c) 2021 Loongson Technology Corporation Limited */ +#ifndef CONFIG_USER_ONLY +#define CHECK_FPE do { \ + if ((ctx->base.tb->flags & HW_FLAGS_EUEN_FPE) == 0) { \ + generate_exception(ctx, EXCCODE_FPD); \ + return false; \ + } \ +} while (0) +#else +#define CHECK_FPE +#endif + static bool gen_fff(DisasContext *ctx, arg_fff *a, void (*func)(TCGv, TCGv_env, TCGv, TCGv)) { + CHECK_FPE; + func(cpu_fpr[a->fd], cpu_env, cpu_fpr[a->fj], cpu_fpr[a->fk]); return true; } @@ -13,6 +26,8 @@ static bool gen_fff(DisasContext *ctx, arg_fff *a, static bool gen_ff(DisasContext *ctx, arg_ff *a, void (*func)(TCGv, TCGv_env, TCGv)) { + CHECK_FPE; + func(cpu_fpr[a->fd], cpu_env, cpu_fpr[a->fj]); return true; } @@ -22,6 +37,9 @@ static bool gen_muladd(DisasContext *ctx, arg_ffff *a, int flag) { TCGv_i32 tflag = tcg_constant_i32(flag); + + CHECK_FPE; + func(cpu_fpr[a->fd], cpu_env, cpu_fpr[a->fj], cpu_fpr[a->fk], cpu_fpr[a->fa], tflag); return true; @@ -29,18 +47,24 @@ static bool gen_muladd(DisasContext *ctx, arg_ffff *a, static bool trans_fcopysign_s(DisasContext *ctx, arg_fcopysign_s *a) { + CHECK_FPE; + tcg_gen_deposit_i64(cpu_fpr[a->fd], cpu_fpr[a->fk], cpu_fpr[a->fj], 0, 31); return true; } static bool trans_fcopysign_d(DisasContext *ctx, arg_fcopysign_d *a) { + CHECK_FPE; + tcg_gen_deposit_i64(cpu_fpr[a->fd], cpu_fpr[a->fk], cpu_fpr[a->fj], 0, 63); return true; } static bool trans_fabs_s(DisasContext *ctx, arg_fabs_s *a) { + CHECK_FPE; + tcg_gen_andi_i64(cpu_fpr[a->fd], cpu_fpr[a->fj], MAKE_64BIT_MASK(0, 31)); gen_nanbox_s(cpu_fpr[a->fd], cpu_fpr[a->fd]); return true; @@ -48,12 +72,16 @@ static bool trans_fabs_s(DisasContext *ctx, arg_fabs_s *a) static bool trans_fabs_d(DisasContext *ctx, arg_fabs_d *a) { + CHECK_FPE; + tcg_gen_andi_i64(cpu_fpr[a->fd], cpu_fpr[a->fj], MAKE_64BIT_MASK(0, 63)); return true; } static bool trans_fneg_s(DisasContext *ctx, arg_fneg_s *a) { + CHECK_FPE; + tcg_gen_xori_i64(cpu_fpr[a->fd], cpu_fpr[a->fj], 0x80000000); gen_nanbox_s(cpu_fpr[a->fd], cpu_fpr[a->fd]); return true; @@ -61,6 +89,8 @@ static bool trans_fneg_s(DisasContext *ctx, arg_fneg_s *a) static bool trans_fneg_d(DisasContext *ctx, arg_fneg_d *a) { + CHECK_FPE; + tcg_gen_xori_i64(cpu_fpr[a->fd], cpu_fpr[a->fj], 0x8000000000000000LL); return true; } diff --git a/target/loongarch/insn_trans/trans_fcmp.c.inc b/target/loongarch/insn_trans/trans_fcmp.c.inc index 93a6a2230f..2ccf646ccb 100644 --- a/target/loongarch/insn_trans/trans_fcmp.c.inc +++ b/target/loongarch/insn_trans/trans_fcmp.c.inc @@ -25,10 +25,13 @@ static uint32_t get_fcmp_flags(int cond) static bool trans_fcmp_cond_s(DisasContext *ctx, arg_fcmp_cond_s *a) { - TCGv var = tcg_temp_new(); + TCGv var; uint32_t flags; void (*fn)(TCGv, TCGv_env, TCGv, TCGv, TCGv_i32); + CHECK_FPE; + + var = tcg_temp_new(); fn = (a->fcond & 1 ? gen_helper_fcmp_s_s : gen_helper_fcmp_c_s); flags = get_fcmp_flags(a->fcond >> 1); @@ -41,9 +44,13 @@ static bool trans_fcmp_cond_s(DisasContext *ctx, arg_fcmp_cond_s *a) static bool trans_fcmp_cond_d(DisasContext *ctx, arg_fcmp_cond_d *a) { - TCGv var = tcg_temp_new(); + TCGv var; uint32_t flags; void (*fn)(TCGv, TCGv_env, TCGv, TCGv, TCGv_i32); + + CHECK_FPE; + + var = tcg_temp_new(); fn = (a->fcond & 1 ? gen_helper_fcmp_s_d : gen_helper_fcmp_c_d); flags = get_fcmp_flags(a->fcond >> 1); diff --git a/target/loongarch/insn_trans/trans_fmemory.c.inc b/target/loongarch/insn_trans/trans_fmemory.c.inc index 74ee98f63a..3025a1d3e9 100644 --- a/target/loongarch/insn_trans/trans_fmemory.c.inc +++ b/target/loongarch/insn_trans/trans_fmemory.c.inc @@ -15,6 +15,8 @@ static bool gen_fload_i(DisasContext *ctx, arg_fr_i *a, MemOp mop) TCGv addr = gpr_src(ctx, a->rj, EXT_NONE); TCGv temp = NULL; + CHECK_FPE; + if (a->imm) { temp = tcg_temp_new(); tcg_gen_addi_tl(temp, addr, a->imm); @@ -36,6 +38,8 @@ static bool gen_fstore_i(DisasContext *ctx, arg_fr_i *a, MemOp mop) TCGv addr = gpr_src(ctx, a->rj, EXT_NONE); TCGv temp = NULL; + CHECK_FPE; + if (a->imm) { temp = tcg_temp_new(); tcg_gen_addi_tl(temp, addr, a->imm); @@ -54,8 +58,11 @@ static bool gen_floadx(DisasContext *ctx, arg_frr *a, MemOp mop) { TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE); TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE); - TCGv addr = tcg_temp_new(); + TCGv addr; + CHECK_FPE; + + addr = tcg_temp_new(); tcg_gen_add_tl(addr, src1, src2); tcg_gen_qemu_ld_tl(cpu_fpr[a->fd], addr, ctx->mem_idx, mop); maybe_nanbox_load(cpu_fpr[a->fd], mop); @@ -68,8 +75,11 @@ static bool gen_fstorex(DisasContext *ctx, arg_frr *a, MemOp mop) { TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE); TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE); - TCGv addr = tcg_temp_new(); + TCGv addr; + + CHECK_FPE; + addr = tcg_temp_new(); tcg_gen_add_tl(addr, src1, src2); tcg_gen_qemu_st_tl(cpu_fpr[a->fd], addr, ctx->mem_idx, mop); tcg_temp_free(addr); @@ -81,8 +91,11 @@ static bool gen_fload_gt(DisasContext *ctx, arg_frr *a, MemOp mop) { TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE); TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE); - TCGv addr = tcg_temp_new(); + TCGv addr; + CHECK_FPE; + + addr = tcg_temp_new(); gen_helper_asrtgt_d(cpu_env, src1, src2); tcg_gen_add_tl(addr, src1, src2); tcg_gen_qemu_ld_tl(cpu_fpr[a->fd], addr, ctx->mem_idx, mop); @@ -96,8 +109,11 @@ static bool gen_fstore_gt(DisasContext *ctx, arg_frr *a, MemOp mop) { TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE); TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE); - TCGv addr = tcg_temp_new(); + TCGv addr; + + CHECK_FPE; + addr = tcg_temp_new(); gen_helper_asrtgt_d(cpu_env, src1, src2); tcg_gen_add_tl(addr, src1, src2); tcg_gen_qemu_st_tl(cpu_fpr[a->fd], addr, ctx->mem_idx, mop); @@ -110,8 +126,11 @@ static bool gen_fload_le(DisasContext *ctx, arg_frr *a, MemOp mop) { TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE); TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE); - TCGv addr = tcg_temp_new(); + TCGv addr; + CHECK_FPE; + + addr = tcg_temp_new(); gen_helper_asrtle_d(cpu_env, src1, src2); tcg_gen_add_tl(addr, src1, src2); tcg_gen_qemu_ld_tl(cpu_fpr[a->fd], addr, ctx->mem_idx, mop); @@ -125,8 +144,11 @@ static bool gen_fstore_le(DisasContext *ctx, arg_frr *a, MemOp mop) { TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE); TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE); - TCGv addr = tcg_temp_new(); + TCGv addr; + + CHECK_FPE; + addr = tcg_temp_new(); gen_helper_asrtle_d(cpu_env, src1, src2); tcg_gen_add_tl(addr, src1, src2); tcg_gen_qemu_st_tl(cpu_fpr[a->fd], addr, ctx->mem_idx, mop); diff --git a/target/loongarch/insn_trans/trans_fmov.c.inc b/target/loongarch/insn_trans/trans_fmov.c.inc index 5537e3dd35..8e5106db4e 100644 --- a/target/loongarch/insn_trans/trans_fmov.c.inc +++ b/target/loongarch/insn_trans/trans_fmov.c.inc @@ -10,8 +10,11 @@ static const uint32_t fcsr_mask[4] = { static bool trans_fsel(DisasContext *ctx, arg_fsel *a) { TCGv zero = tcg_constant_tl(0); - TCGv cond = tcg_temp_new(); + TCGv cond; + CHECK_FPE; + + cond = tcg_temp_new(); tcg_gen_ld8u_tl(cond, cpu_env, offsetof(CPULoongArchState, cf[a->ca])); tcg_gen_movcond_tl(TCG_COND_EQ, cpu_fpr[a->fd], cond, zero, cpu_fpr[a->fj], cpu_fpr[a->fk]); @@ -26,6 +29,8 @@ static bool gen_f2f(DisasContext *ctx, arg_ff *a, TCGv dest = cpu_fpr[a->fd]; TCGv src = cpu_fpr[a->fj]; + CHECK_FPE; + func(dest, src); if (nanbox) { gen_nanbox_s(cpu_fpr[a->fd], cpu_fpr[a->fd]); @@ -39,6 +44,8 @@ static bool gen_r2f(DisasContext *ctx, arg_fr *a, { TCGv src = gpr_src(ctx, a->rj, EXT_NONE); + CHECK_FPE; + func(cpu_fpr[a->fd], src); return true; } @@ -48,6 +55,8 @@ static bool gen_f2r(DisasContext *ctx, arg_rf *a, { TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE); + CHECK_FPE; + func(dest, cpu_fpr[a->fj]); gen_set_gpr(a->rd, dest, EXT_NONE); @@ -59,6 +68,8 @@ static bool trans_movgr2fcsr(DisasContext *ctx, arg_movgr2fcsr *a) uint32_t mask = fcsr_mask[a->fcsrd]; TCGv Rj = gpr_src(ctx, a->rj, EXT_NONE); + CHECK_FPE; + if (mask == UINT32_MAX) { tcg_gen_st32_i64(Rj, cpu_env, offsetof(CPULoongArchState, fcsr0)); } else { @@ -90,6 +101,8 @@ static bool trans_movfcsr2gr(DisasContext *ctx, arg_movfcsr2gr *a) { TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE); + CHECK_FPE; + tcg_gen_ld32u_i64(dest, cpu_env, offsetof(CPULoongArchState, fcsr0)); tcg_gen_andi_i64(dest, dest, fcsr_mask[a->fcsrs]); gen_set_gpr(a->rd, dest, EXT_NONE); @@ -114,8 +127,11 @@ static void gen_movfrh2gr_s(TCGv dest, TCGv src) static bool trans_movfr2cf(DisasContext *ctx, arg_movfr2cf *a) { - TCGv t0 = tcg_temp_new(); + TCGv t0; + + CHECK_FPE; + t0 = tcg_temp_new(); tcg_gen_andi_tl(t0, cpu_fpr[a->fj], 0x1); tcg_gen_st8_tl(t0, cpu_env, offsetof(CPULoongArchState, cf[a->cd & 0x7])); tcg_temp_free(t0); @@ -125,6 +141,8 @@ static bool trans_movfr2cf(DisasContext *ctx, arg_movfr2cf *a) static bool trans_movcf2fr(DisasContext *ctx, arg_movcf2fr *a) { + CHECK_FPE; + tcg_gen_ld8u_tl(cpu_fpr[a->fd], cpu_env, offsetof(CPULoongArchState, cf[a->cj & 0x7])); return true; @@ -132,8 +150,11 @@ static bool trans_movcf2fr(DisasContext *ctx, arg_movcf2fr *a) static bool trans_movgr2cf(DisasContext *ctx, arg_movgr2cf *a) { - TCGv t0 = tcg_temp_new(); + TCGv t0; + CHECK_FPE; + + t0 = tcg_temp_new(); tcg_gen_andi_tl(t0, gpr_src(ctx, a->rj, EXT_NONE), 0x1); tcg_gen_st8_tl(t0, cpu_env, offsetof(CPULoongArchState, cf[a->cd & 0x7])); tcg_temp_free(t0); @@ -143,6 +164,8 @@ static bool trans_movgr2cf(DisasContext *ctx, arg_movgr2cf *a) static bool trans_movcf2gr(DisasContext *ctx, arg_movcf2gr *a) { + CHECK_FPE; + tcg_gen_ld8u_tl(gpr_dst(ctx, a->rd, EXT_NONE), cpu_env, offsetof(CPULoongArchState, cf[a->cj & 0x7])); return true; diff --git a/target/loongarch/insn_trans/trans_privileged.c.inc b/target/loongarch/insn_trans/trans_privileged.c.inc index 9c4dcbfcfb..ff3a6d95ae 100644 --- a/target/loongarch/insn_trans/trans_privileged.c.inc +++ b/target/loongarch/insn_trans/trans_privileged.c.inc @@ -159,7 +159,7 @@ static const CSRInfo csr_info[] = { static bool check_plv(DisasContext *ctx) { - if (ctx->base.tb->flags == MMU_USER_IDX) { + if (ctx->mem_idx == MMU_USER_IDX) { generate_exception(ctx, EXCCODE_IPE); return true; } diff --git a/target/loongarch/iocsr_helper.c b/target/loongarch/iocsr_helper.c index 0e9c537dc7..505853e17b 100644 --- a/target/loongarch/iocsr_helper.c +++ b/target/loongarch/iocsr_helper.c @@ -14,54 +14,57 @@ #include "exec/cpu_ldst.h" #include "tcg/tcg-ldst.h" +#define GET_MEMTXATTRS(cas) \ + ((MemTxAttrs){.requester_id = env_cpu(cas)->cpu_index}) + uint64_t helper_iocsrrd_b(CPULoongArchState *env, target_ulong r_addr) { return address_space_ldub(&env->address_space_iocsr, r_addr, - MEMTXATTRS_UNSPECIFIED, NULL); + GET_MEMTXATTRS(env), NULL); } uint64_t helper_iocsrrd_h(CPULoongArchState *env, target_ulong r_addr) { return address_space_lduw(&env->address_space_iocsr, r_addr, - MEMTXATTRS_UNSPECIFIED, NULL); + GET_MEMTXATTRS(env), NULL); } uint64_t helper_iocsrrd_w(CPULoongArchState *env, target_ulong r_addr) { return address_space_ldl(&env->address_space_iocsr, r_addr, - MEMTXATTRS_UNSPECIFIED, NULL); + GET_MEMTXATTRS(env), NULL); } uint64_t helper_iocsrrd_d(CPULoongArchState *env, target_ulong r_addr) { return address_space_ldq(&env->address_space_iocsr, r_addr, - MEMTXATTRS_UNSPECIFIED, NULL); + GET_MEMTXATTRS(env), NULL); } void helper_iocsrwr_b(CPULoongArchState *env, target_ulong w_addr, target_ulong val) { address_space_stb(&env->address_space_iocsr, w_addr, - val, MEMTXATTRS_UNSPECIFIED, NULL); + val, GET_MEMTXATTRS(env), NULL); } void helper_iocsrwr_h(CPULoongArchState *env, target_ulong w_addr, target_ulong val) { address_space_stw(&env->address_space_iocsr, w_addr, - val, MEMTXATTRS_UNSPECIFIED, NULL); + val, GET_MEMTXATTRS(env), NULL); } void helper_iocsrwr_w(CPULoongArchState *env, target_ulong w_addr, target_ulong val) { address_space_stl(&env->address_space_iocsr, w_addr, - val, MEMTXATTRS_UNSPECIFIED, NULL); + val, GET_MEMTXATTRS(env), NULL); } void helper_iocsrwr_d(CPULoongArchState *env, target_ulong w_addr, target_ulong val) { address_space_stq(&env->address_space_iocsr, w_addr, - val, MEMTXATTRS_UNSPECIFIED, NULL); + val, GET_MEMTXATTRS(env), NULL); } diff --git a/target/loongarch/tlb_helper.c b/target/loongarch/tlb_helper.c index 610b6d123c..d2f8fb0c60 100644 --- a/target/loongarch/tlb_helper.c +++ b/target/loongarch/tlb_helper.c @@ -229,7 +229,8 @@ static void raise_mmu_exception(CPULoongArchState *env, target_ulong address, switch (tlb_error) { default: case TLBRET_BADADDR: - cs->exception_index = EXCCODE_ADEM; + cs->exception_index = access_type == MMU_INST_FETCH + ? EXCCODE_ADEF : EXCCODE_ADEM; break; case TLBRET_NOMATCH: /* No TLB match for a mapped address */ @@ -643,7 +644,7 @@ bool loongarch_cpu_tlb_fill(CPUState *cs, vaddr address, int size, CPULoongArchState *env = &cpu->env; hwaddr physical; int prot; - int ret = TLBRET_BADADDR; + int ret; /* Data access */ ret = get_physical_address(env, &physical, &prot, address, diff --git a/target/loongarch/translate.c b/target/loongarch/translate.c index 6091772349..31462b2b61 100644 --- a/target/loongarch/translate.c +++ b/target/loongarch/translate.c @@ -75,7 +75,11 @@ static void loongarch_tr_init_disas_context(DisasContextBase *dcbase, DisasContext *ctx = container_of(dcbase, DisasContext, base); ctx->page_start = ctx->base.pc_first & TARGET_PAGE_MASK; - ctx->mem_idx = ctx->base.tb->flags; + if (ctx->base.tb->flags & HW_FLAGS_CRMD_PG) { + ctx->mem_idx = ctx->base.tb->flags & HW_FLAGS_PLV_MASK; + } else { + ctx->mem_idx = MMU_DA_IDX; + } /* Bound the number of insns to execute to those left on the page. */ bound = -(ctx->base.pc_first | TARGET_PAGE_MASK) / 4; |