From ac9b0117d545d4e318c6827251fdf654385188f5 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Fri, 22 Jan 2021 20:24:04 +0800 Subject: hw/mips: loongson3: Drop 'struct MemmapEntry' There is already a MemMapEntry type defined in hwaddr.h. Let's drop the loongson3 defined `struct MemmapEntry` and use the existing one. Signed-off-by: Bin Meng Reviewed-by: Philippe Mathieu-Daudé Tested-by: Philippe Mathieu-Daudé Message-Id: <20210122122404.11970-1-bmeng.cn@gmail.com> Signed-off-by: Philippe Mathieu-Daudé --- hw/mips/loongson3_bootp.h | 7 +------ hw/mips/loongson3_virt.c | 6 +++--- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/hw/mips/loongson3_bootp.h b/hw/mips/loongson3_bootp.h index 09f8480abf..d525ab745a 100644 --- a/hw/mips/loongson3_bootp.h +++ b/hw/mips/loongson3_bootp.h @@ -228,12 +228,7 @@ enum { LOADER_PARAM, }; -struct MemmapEntry { - hwaddr base; - hwaddr size; -}; - -extern const struct MemmapEntry virt_memmap[]; +extern const MemMapEntry virt_memmap[]; void init_loongson_params(struct loongson_params *lp, void *p, uint64_t cpu_freq, uint64_t ram_size); void init_reset_system(struct efi_reset_system_t *reset); diff --git a/hw/mips/loongson3_virt.c b/hw/mips/loongson3_virt.c index d4a82fa536..b15071defc 100644 --- a/hw/mips/loongson3_virt.c +++ b/hw/mips/loongson3_virt.c @@ -72,7 +72,7 @@ #define RTC_IRQ 1 #define PCIE_IRQ_BASE 2 -const struct MemmapEntry virt_memmap[] = { +const MemMapEntry virt_memmap[] = { [VIRT_LOWMEM] = { 0x00000000, 0x10000000 }, [VIRT_PM] = { 0x10080000, 0x100 }, [VIRT_FW_CFG] = { 0x10080100, 0x100 }, @@ -86,13 +86,13 @@ const struct MemmapEntry virt_memmap[] = { [VIRT_HIGHMEM] = { 0x80000000, 0x0 }, /* Variable */ }; -static const struct MemmapEntry loader_memmap[] = { +static const MemMapEntry loader_memmap[] = { [LOADER_KERNEL] = { 0x00000000, 0x4000000 }, [LOADER_INITRD] = { 0x04000000, 0x0 }, /* Variable */ [LOADER_CMDLINE] = { 0x0ff00000, 0x100000 }, }; -static const struct MemmapEntry loader_rommap[] = { +static const MemMapEntry loader_rommap[] = { [LOADER_BOOTROM] = { 0x1fc00000, 0x1000 }, [LOADER_PARAM] = { 0x1fc01000, 0x10000 }, }; -- cgit v1.2.3-55-g7522 From 3ebbf86128f5607831ba5a3dec8bac02271a9390 Mon Sep 17 00:00:00 2001 From: Jiaxun Yang Date: Wed, 27 Jan 2021 14:54:21 +0800 Subject: hw/mips: Add a bootloader helper Add a bootloader helper to generate simple bootloaders for kernel. It can help us reduce inline hex hack and also keep MIPS release 6 compatibility easier. Signed-off-by: Jiaxun Yang Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20210127065424.114125-2-jiaxun.yang@flygoat.com> [PMD: Restricted bl_reg enum to C source, inverted bl_gen_write() args, added license in hw/mips/bootloader.h] Signed-off-by: Philippe Mathieu-Daudé --- hw/mips/bootloader.c | 200 +++++++++++++++++++++++++++++++++++++++++++ hw/mips/meson.build | 2 +- include/hw/mips/bootloader.h | 22 +++++ 3 files changed, 223 insertions(+), 1 deletion(-) create mode 100644 hw/mips/bootloader.c create mode 100644 include/hw/mips/bootloader.h diff --git a/hw/mips/bootloader.c b/hw/mips/bootloader.c new file mode 100644 index 0000000000..6ec8314490 --- /dev/null +++ b/hw/mips/bootloader.c @@ -0,0 +1,200 @@ +/* + * Utility for QEMU MIPS to generate it's simple bootloader + * + * Instructions used here are carefully selected to keep compatibility with + * MIPS Release 6. + * + * Copyright (C) 2020 Jiaxun Yang + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "qemu/osdep.h" +#include "qemu/bitops.h" +#include "cpu.h" +#include "hw/mips/bootloader.h" + +typedef enum bl_reg { + BL_REG_ZERO = 0, + BL_REG_AT = 1, + BL_REG_V0 = 2, + BL_REG_V1 = 3, + BL_REG_A0 = 4, + BL_REG_A1 = 5, + BL_REG_A2 = 6, + BL_REG_A3 = 7, + BL_REG_T0 = 8, + BL_REG_T1 = 9, + BL_REG_T2 = 10, + BL_REG_T3 = 11, + BL_REG_T4 = 12, + BL_REG_T5 = 13, + BL_REG_T6 = 14, + BL_REG_T7 = 15, + BL_REG_S0 = 16, + BL_REG_S1 = 17, + BL_REG_S2 = 18, + BL_REG_S3 = 19, + BL_REG_S4 = 20, + BL_REG_S5 = 21, + BL_REG_S6 = 22, + BL_REG_S7 = 23, + BL_REG_T8 = 24, + BL_REG_T9 = 25, + BL_REG_K0 = 26, + BL_REG_K1 = 27, + BL_REG_GP = 28, + BL_REG_SP = 29, + BL_REG_FP = 30, + BL_REG_RA = 31, +} bl_reg; + +static bool bootcpu_supports_isa(uint64_t isa_mask) +{ + return cpu_supports_isa(&MIPS_CPU(first_cpu)->env, isa_mask); +} + +/* Base types */ +static void bl_gen_nop(uint32_t **p) +{ + stl_p(*p, 0); + *p = *p + 1; +} + +static void bl_gen_r_type(uint32_t **p, uint8_t opcode, + bl_reg rs, bl_reg rt, bl_reg rd, + uint8_t shift, uint8_t funct) +{ + uint32_t insn = 0; + + insn = deposit32(insn, 26, 6, opcode); + insn = deposit32(insn, 21, 5, rs); + insn = deposit32(insn, 16, 5, rt); + insn = deposit32(insn, 11, 5, rd); + insn = deposit32(insn, 6, 5, shift); + insn = deposit32(insn, 0, 6, funct); + + stl_p(*p, insn); + *p = *p + 1; +} + +static void bl_gen_i_type(uint32_t **p, uint8_t opcode, + bl_reg rs, bl_reg rt, uint16_t imm) +{ + uint32_t insn = 0; + + insn = deposit32(insn, 26, 6, opcode); + insn = deposit32(insn, 21, 5, rs); + insn = deposit32(insn, 16, 5, rt); + insn = deposit32(insn, 0, 16, imm); + + stl_p(*p, insn); + *p = *p + 1; +} + +/* Single instructions */ +static void bl_gen_dsll(uint32_t **p, bl_reg rd, bl_reg rt, uint8_t sa) +{ + if (bootcpu_supports_isa(ISA_MIPS3)) { + bl_gen_r_type(p, 0, 0, rt, rd, sa, 0x38); + } else { + g_assert_not_reached(); /* unsupported */ + } +} + +static void bl_gen_jalr(uint32_t **p, bl_reg rs) +{ + bl_gen_r_type(p, 0, rs, 0, BL_REG_RA, 0, 0x09); +} + +static void bl_gen_lui(uint32_t **p, bl_reg rt, uint16_t imm) +{ + /* R6: It's a alias of AUI with RS = 0 */ + bl_gen_i_type(p, 0x0f, 0, rt, imm); +} + +static void bl_gen_ori(uint32_t **p, bl_reg rt, bl_reg rs, uint16_t imm) +{ + bl_gen_i_type(p, 0x0d, rs, rt, imm); +} + +static void bl_gen_sw(uint32_t **p, bl_reg rt, uint8_t base, uint16_t offset) +{ + bl_gen_i_type(p, 0x2b, base, rt, offset); +} + +static void bl_gen_sd(uint32_t **p, bl_reg rt, uint8_t base, uint16_t offset) +{ + if (bootcpu_supports_isa(ISA_MIPS3)) { + bl_gen_i_type(p, 0x3f, base, rt, offset); + } else { + g_assert_not_reached(); /* unsupported */ + } +} + +/* Pseudo instructions */ +static void bl_gen_li(uint32_t **p, bl_reg rt, uint32_t imm) +{ + bl_gen_lui(p, rt, extract32(imm, 16, 16)); + bl_gen_ori(p, rt, rt, extract32(imm, 0, 16)); +} + +static void bl_gen_dli(uint32_t **p, bl_reg rt, uint64_t imm) +{ + bl_gen_li(p, rt, extract64(imm, 32, 32)); + bl_gen_dsll(p, rt, rt, 16); + bl_gen_ori(p, rt, rt, extract64(imm, 16, 16)); + bl_gen_dsll(p, rt, rt, 16); + bl_gen_ori(p, rt, rt, extract64(imm, 0, 16)); +} + +static void bl_gen_load_ulong(uint32_t **p, bl_reg rt, target_ulong imm) +{ + if (bootcpu_supports_isa(ISA_MIPS3)) { + bl_gen_dli(p, rt, imm); /* 64bit */ + } else { + bl_gen_li(p, rt, imm); /* 32bit */ + } +} + +/* Helpers */ +void bl_gen_jump_to(uint32_t **p, target_ulong jump_addr) +{ + bl_gen_load_ulong(p, BL_REG_T9, jump_addr); + bl_gen_jalr(p, BL_REG_T9); + bl_gen_nop(p); /* delay slot */ +} + +void bl_gen_jump_kernel(uint32_t **p, target_ulong sp, target_ulong a0, + target_ulong a1, target_ulong a2, target_ulong a3, + target_ulong kernel_addr) +{ + bl_gen_load_ulong(p, BL_REG_SP, sp); + bl_gen_load_ulong(p, BL_REG_A0, a0); + bl_gen_load_ulong(p, BL_REG_A1, a1); + bl_gen_load_ulong(p, BL_REG_A2, a2); + bl_gen_load_ulong(p, BL_REG_A3, a3); + + bl_gen_jump_to(p, kernel_addr); +} + +void bl_gen_write_ulong(uint32_t **p, target_ulong addr, target_ulong val) +{ + bl_gen_load_ulong(p, BL_REG_K0, val); + bl_gen_load_ulong(p, BL_REG_K1, addr); + bl_gen_sd(p, BL_REG_K0, BL_REG_K1, 0x0); +} + +void bl_gen_write_u32(uint32_t **p, target_ulong addr, uint32_t val) +{ + bl_gen_li(p, BL_REG_K0, val); + bl_gen_load_ulong(p, BL_REG_K1, addr); + bl_gen_sw(p, BL_REG_K0, BL_REG_K1, 0x0); +} + +void bl_gen_write_u64(uint32_t **p, target_ulong addr, uint64_t val) +{ + bl_gen_dli(p, BL_REG_K0, val); + bl_gen_load_ulong(p, BL_REG_K1, addr); + bl_gen_sd(p, BL_REG_K0, BL_REG_K1, 0x0); +} diff --git a/hw/mips/meson.build b/hw/mips/meson.build index ee19cc204d..1195716dc7 100644 --- a/hw/mips/meson.build +++ b/hw/mips/meson.build @@ -1,5 +1,5 @@ mips_ss = ss.source_set() -mips_ss.add(files('mips_int.c')) +mips_ss.add(files('bootloader.c', 'mips_int.c')) mips_ss.add(when: 'CONFIG_FW_CFG_MIPS', if_true: files('fw_cfg.c')) mips_ss.add(when: 'CONFIG_FULOONG', if_true: files('fuloong2e.c')) mips_ss.add(when: 'CONFIG_LOONGSON3V', if_true: files('loongson3_bootp.c', 'loongson3_virt.c')) diff --git a/include/hw/mips/bootloader.h b/include/hw/mips/bootloader.h new file mode 100644 index 0000000000..b5f48d71bb --- /dev/null +++ b/include/hw/mips/bootloader.h @@ -0,0 +1,22 @@ +/* + * Utility for QEMU MIPS to generate it's simple bootloader + * + * Copyright (C) 2020 Jiaxun Yang + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef HW_MIPS_BOOTLOADER_H +#define HW_MIPS_BOOTLOADER_H + +#include "exec/cpu-defs.h" + +void bl_gen_jump_to(uint32_t **p, target_ulong jump_addr); +void bl_gen_jump_kernel(uint32_t **p, target_ulong sp, target_ulong a0, + target_ulong a1, target_ulong a2, target_ulong a3, + target_ulong kernel_addr); +void bl_gen_write_ulong(uint32_t **p, target_ulong addr, target_ulong val); +void bl_gen_write_u32(uint32_t **p, target_ulong addr, uint32_t val); +void bl_gen_write_u64(uint32_t **p, target_ulong addr, uint64_t val); + +#endif -- cgit v1.2.3-55-g7522 From 4d0c59fa07933f64ba8df9da1f76154869ba9425 Mon Sep 17 00:00:00 2001 From: Jiaxun Yang Date: Tue, 15 Dec 2020 14:45:05 +0800 Subject: hw/mips/fuloong2e: Use bl_gen_kernel_jump to generate bootloaders Replace embedded binary with generated code. Signed-off-by: Jiaxun Yang Tested-by: Philippe Mathieu-Daudé Message-Id: <20201215064507.30148-2-jiaxun.yang@flygoat.com> Reviewed-by: Philippe Mathieu-Daudé [PMD: Split original patch as one for each machine (here fuloong2e)] Signed-off-by: Philippe Mathieu-Daudé --- hw/mips/fuloong2e.c | 27 +++------------------------ 1 file changed, 3 insertions(+), 24 deletions(-) diff --git a/hw/mips/fuloong2e.c b/hw/mips/fuloong2e.c index bac2adbd5a..1f3680fda3 100644 --- a/hw/mips/fuloong2e.c +++ b/hw/mips/fuloong2e.c @@ -33,6 +33,7 @@ #include "hw/i2c/smbus_eeprom.h" #include "hw/block/flash.h" #include "hw/mips/mips.h" +#include "hw/mips/bootloader.h" #include "hw/mips/cpudevs.h" #include "hw/pci/pci.h" #include "qemu/log.h" @@ -185,30 +186,8 @@ static void write_bootloader(CPUMIPSState *env, uint8_t *base, /* Second part of the bootloader */ p = (uint32_t *)(base + 0x040); - /* lui a0, 0 */ - stl_p(p++, 0x3c040000); - /* ori a0, a0, 2 */ - stl_p(p++, 0x34840002); - /* lui a1, high(ENVP_VADDR) */ - stl_p(p++, 0x3c050000 | ((ENVP_VADDR >> 16) & 0xffff)); - /* ori a1, a0, low(ENVP_VADDR) */ - stl_p(p++, 0x34a50000 | (ENVP_VADDR & 0xffff)); - /* lui a2, high(ENVP_VADDR + 8) */ - stl_p(p++, 0x3c060000 | (((ENVP_VADDR + 8) >> 16) & 0xffff)); - /* ori a2, a2, low(ENVP_VADDR + 8) */ - stl_p(p++, 0x34c60000 | ((ENVP_VADDR + 8) & 0xffff)); - /* lui a3, high(env->ram_size) */ - stl_p(p++, 0x3c070000 | (loaderparams.ram_size >> 16)); - /* ori a3, a3, low(env->ram_size) */ - stl_p(p++, 0x34e70000 | (loaderparams.ram_size & 0xffff)); - /* lui ra, high(kernel_addr) */ - stl_p(p++, 0x3c1f0000 | ((kernel_addr >> 16) & 0xffff)); - /* ori ra, ra, low(kernel_addr) */ - stl_p(p++, 0x37ff0000 | (kernel_addr & 0xffff)); - /* jr ra */ - stl_p(p++, 0x03e00008); - /* nop */ - stl_p(p++, 0x00000000); + bl_gen_jump_kernel(&p, ENVP_VADDR - 64, 2, ENVP_VADDR, ENVP_VADDR + 8, + loaderparams.ram_size, kernel_addr); } static void main_cpu_reset(void *opaque) -- cgit v1.2.3-55-g7522 From 112658eb26382a7e9717d8bef716ac4675799719 Mon Sep 17 00:00:00 2001 From: Jiaxun Yang Date: Tue, 15 Dec 2020 14:45:05 +0800 Subject: hw/mips/boston: Use bl_gen_kernel_jump to generate bootloaders Replace embedded binary with generated code. Signed-off-by: Jiaxun Yang Tested-by: Philippe Mathieu-Daudé Message-Id: <20201215064507.30148-2-jiaxun.yang@flygoat.com> Reviewed-by: Philippe Mathieu-Daudé [PMD: Split original patch as one for each machine (here boston)] Signed-off-by: Philippe Mathieu-Daudé --- hw/mips/boston.c | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) diff --git a/hw/mips/boston.c b/hw/mips/boston.c index 467fbc1c8b..b976c8199a 100644 --- a/hw/mips/boston.c +++ b/hw/mips/boston.c @@ -27,6 +27,7 @@ #include "hw/ide/ahci.h" #include "hw/loader.h" #include "hw/loader-fit.h" +#include "hw/mips/bootloader.h" #include "hw/mips/cps.h" #include "hw/pci-host/xilinx-pcie.h" #include "hw/qdev-clock.h" @@ -324,21 +325,7 @@ static void gen_firmware(uint32_t *p, hwaddr kernel_entry, hwaddr fdt_addr, * a2/$6 = 0 * a3/$7 = 0 */ - stl_p(p++, 0x2404fffe); /* li $4, -2 */ - /* lui $5, hi(fdt_addr) */ - stl_p(p++, 0x3c050000 | ((fdt_addr >> 16) & 0xffff)); - if (fdt_addr & 0xffff) { /* ori $5, lo(fdt_addr) */ - stl_p(p++, 0x34a50000 | (fdt_addr & 0xffff)); - } - stl_p(p++, 0x34060000); /* li $6, 0 */ - stl_p(p++, 0x34070000); /* li $7, 0 */ - - /* Load kernel entry address & jump to it */ - /* lui $25, hi(kernel_entry) */ - stl_p(p++, 0x3c190000 | ((kernel_entry >> 16) & 0xffff)); - /* ori $25, lo(kernel_entry) */ - stl_p(p++, 0x37390000 | (kernel_entry & 0xffff)); - stl_p(p++, 0x03200009); /* jr $25 */ + bl_gen_jump_kernel(&p, 0, (int32_t)-2, fdt_addr, 0, 0, kernel_entry); } static const void *boston_fdt_filter(void *opaque, const void *fdt_orig, -- cgit v1.2.3-55-g7522 From 283eae174e4944e4f26160aceeec444a13e52b03 Mon Sep 17 00:00:00 2001 From: Jiaxun Yang Date: Wed, 27 Jan 2021 14:54:24 +0800 Subject: hw/mips/boston: Use bootloader helper to set GCRs Translate embedded assembly into IO writes which is more readable. Also hardcode cm_base at boot time instead of reading from CP0. Signed-off-by: Jiaxun Yang Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20210127065424.114125-5-jiaxun.yang@flygoat.com> [PMD: Kept code comments] Signed-off-by: Philippe Mathieu-Daudé --- hw/mips/boston.c | 45 +++++++++++---------------------------------- 1 file changed, 11 insertions(+), 34 deletions(-) diff --git a/hw/mips/boston.c b/hw/mips/boston.c index b976c8199a..ac2e93a05a 100644 --- a/hw/mips/boston.c +++ b/hw/mips/boston.c @@ -274,48 +274,26 @@ static void boston_register_types(void) } type_init(boston_register_types) -static void gen_firmware(uint32_t *p, hwaddr kernel_entry, hwaddr fdt_addr, - bool is_64b) +static void gen_firmware(uint32_t *p, hwaddr kernel_entry, hwaddr fdt_addr) { const uint32_t cm_base = 0x16100000; const uint32_t gic_base = 0x16120000; const uint32_t cpc_base = 0x16200000; /* Move CM GCRs */ - if (is_64b) { - stl_p(p++, 0x40287803); /* dmfc0 $8, CMGCRBase */ - stl_p(p++, 0x00084138); /* dsll $8, $8, 4 */ - } else { - stl_p(p++, 0x40087803); /* mfc0 $8, CMGCRBase */ - stl_p(p++, 0x00084100); /* sll $8, $8, 4 */ - } - stl_p(p++, 0x3c09a000); /* lui $9, 0xa000 */ - stl_p(p++, 0x01094025); /* or $8, $9 */ - stl_p(p++, 0x3c0a0000 | (cm_base >> 16)); /* lui $10, cm_base >> 16 */ - if (is_64b) { - stl_p(p++, 0xfd0a0008); /* sd $10, 0x8($8) */ - } else { - stl_p(p++, 0xad0a0008); /* sw $10, 0x8($8) */ - } - stl_p(p++, 0x012a4025); /* or $8, $10 */ + bl_gen_write_ulong(&p, + cpu_mips_phys_to_kseg1(NULL, GCR_BASE_ADDR + GCR_BASE_OFS), + cm_base); /* Move & enable GIC GCRs */ - stl_p(p++, 0x3c090000 | (gic_base >> 16)); /* lui $9, gic_base >> 16 */ - stl_p(p++, 0x35290001); /* ori $9, 0x1 */ - if (is_64b) { - stl_p(p++, 0xfd090080); /* sd $9, 0x80($8) */ - } else { - stl_p(p++, 0xad090080); /* sw $9, 0x80($8) */ - } + bl_gen_write_ulong(&p, + cpu_mips_phys_to_kseg1(NULL, cm_base + GCR_GIC_BASE_OFS), + gic_base | GCR_GIC_BASE_GICEN_MSK); /* Move & enable CPC GCRs */ - stl_p(p++, 0x3c090000 | (cpc_base >> 16)); /* lui $9, cpc_base >> 16 */ - stl_p(p++, 0x35290001); /* ori $9, 0x1 */ - if (is_64b) { - stl_p(p++, 0xfd090088); /* sd $9, 0x88($8) */ - } else { - stl_p(p++, 0xad090088); /* sw $9, 0x88($8) */ - } + bl_gen_write_ulong(&p, + cpu_mips_phys_to_kseg1(NULL, cm_base + GCR_CPC_BASE_OFS), + cpc_base | GCR_CPC_BASE_CPCEN_MSK); /* * Setup argument registers to follow the UHI boot protocol: @@ -529,8 +507,7 @@ static void boston_mach_init(MachineState *machine) } gen_firmware(memory_region_get_ram_ptr(flash) + 0x7c00000, - s->kernel_entry, s->fdt_base, - cpu_type_is_64bit(machine->cpu_type)); + s->kernel_entry, s->fdt_base); } else if (!qtest_enabled()) { error_report("Please provide either a -kernel or -bios argument"); exit(1); -- cgit v1.2.3-55-g7522 From 6902759965852ae9fc099bb32af8f8dc4a098733 Mon Sep 17 00:00:00 2001 From: Jiaxun Yang Date: Tue, 12 Jan 2021 09:25:27 +0800 Subject: hw/intc/loongson_liointc: Fix per core ISR handling Per core ISR is a set of 32-bit registers spaced by 8 bytes. This patch fixed calculation of it's size and also added check of alignment at reading & writing. Fixes: Coverity CID 1438965 and CID 1438967 Signed-off-by: Jiaxun Yang Reviewed-by: Huacai Chen Message-Id: <20210112012527.28927-1-jiaxun.yang@flygoat.com> [PMD: Added Coverity CID] Signed-off-by: Philippe Mathieu-Daudé --- hw/intc/loongson_liointc.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/hw/intc/loongson_liointc.c b/hw/intc/loongson_liointc.c index f823d484e0..cc11b544cb 100644 --- a/hw/intc/loongson_liointc.c +++ b/hw/intc/loongson_liointc.c @@ -41,7 +41,7 @@ #define R_IEN_CLR 0x2c #define R_ISR_SIZE 0x8 #define R_START 0x40 -#define R_END 0x64 +#define R_END (R_START + R_ISR_SIZE * NUM_CORES) struct loongson_liointc { SysBusDevice parent_obj; @@ -125,7 +125,12 @@ liointc_read(void *opaque, hwaddr addr, unsigned int size) } if (addr >= R_START && addr < R_END) { - int core = (addr - R_START) / R_ISR_SIZE; + hwaddr offset = addr - R_START; + int core = offset / R_ISR_SIZE; + + if (offset % R_ISR_SIZE) { + goto out; + } r = p->per_core_isr[core]; goto out; } @@ -169,7 +174,12 @@ liointc_write(void *opaque, hwaddr addr, } if (addr >= R_START && addr < R_END) { - int core = (addr - R_START) / R_ISR_SIZE; + hwaddr offset = addr - R_START; + int core = offset / R_ISR_SIZE; + + if (offset % R_ISR_SIZE) { + goto out; + } p->per_core_isr[core] = value; goto out; } -- cgit v1.2.3-55-g7522 From c0928e6ddcbd8c8e8d3d2901eb0fd076ee2dd17d Mon Sep 17 00:00:00 2001 From: Jiaxun Yang Date: Tue, 12 Jan 2021 10:07:08 +0800 Subject: tests/acceptance: Test PMON with Loongson-3A1000 CPU Test booting of PMON bootloader on loongson3-virt platform. $ (venv) AVOCADO_ALLOW_UNTRUSTED_CODE=1 \ avocado --show=app,console \ run -t machine:loongson3-virt tests/acceptance Fetching asset from tests/acceptance/machine_mips_loongson3v.py:MipsLoongson3v.test_pmon_serial_console JOB ID : 8e202b3727847c9104d0d3d6546ed225d35f6706 JOB LOG : /home/flygoat/avocado/job-results/job-2021-01-12T10.02-8e202b3/job.log (1/1) tests/acceptance/machine_mips_loongson3v.py:MipsLoongson3v.test_pmon_serial_console: console: PMON2000 MIPS Initializing. Standby... console: 00000000Jump to 9fc console: Init Memory done. console: The uncache data is: console: 00000000: 5555555555555555 console: 00000008: aaaaaaaaaaaaaaaa console: 00000010: 3333333333333333 console: 00000018: cccccccccccccccc console: 00000020: 7777777777777777 console: 00000028: 8888888888888888 console: 00000030: 1111111111111111 console: 00000038: eeeeeeeeeeeeeeee console: The cached data is: console: 00000000: 5555555555555555 console: 00000008: aaaaaaaaaaaaaaaa console: 00000010: 3333333333333333 console: 00000018: cccccccccccccccc console: 00000020: 7777777777777777 console: 00000028: 8888888888888888 console: 00000030: 1111111111111111 console: 00000038: eeeeeeeeeeeeeeee console: Copy PMON to execute location... console: start = 0x8f900000 console: s0 = 0x30300000 console: _edata = 0x8f989010 console: _end = 0x8f98a028copy text section done. console: Copy PMON to execute location done. console: sp=8f8fc000 console: Uncompressing Bios............................................................................OK,Booting Bios console: FREQ console: DONE console: DEVI console: ENVI console: MAPV console: NVRAM@8f7ff898 console: STDV console: 80100000: memory between 8f7ff400-8f800000 is already been allocated,heap is already above this point console: SBDD console: P12PCIH console: PCIH console: PCID console: setting up 1 bus console: PCI bus 0 slot 1: probe...completed console: PCI bus 0 slot 1/0: vendor/product: 0x106b/0x003f (serialbus, USB, interface: 0x10, revision: 0x00) console: PCI bus 0 slot 1/0: reg 0x10 = 0xffffff00 console: PCI bus 0 slot 2: probe...completed console: PCI bus 0 slot 2/0: vendor/product: 0x1af4/0x1000 (network, ethernet, interface: 0x00, revision: 0x00) console: PCI bus 0 slot 2/0: reg 0x10 = 0xffffffe1 console: PCI bus 0 slot 2/0: reg 0x14 = 0xfffff000 console: PCI bus 0 slot 2/0: reg 0x20 = 0xffffc00c console: PCI bus 0 slot 2/0: reg 0x30 = 0xfffc0000 console: PCI bus 0 slot 3: probe...completed console: PCI bus 0 slot 4: probe...completed console: PCI bus 0 slot 5: probe...completed console: PCI bus 0 slot 6: probe...completed console: PCI bus 0 slot 7: probe...completed console: PCI bus 0 slot 8: probe...completed console: PCI bus 0 slot 9: probe...completed console: PCI bus 0 slot 10: probe...completed console: PCI bus 0 slot 11: probe...completed console: PCI bus 0 slot 12: probe...completed console: PCI bus 0 slot 13: probe...completed console: PCI bus 0 slot 14: probe...completed console: PCI bus 0 slot 15: probe...completed console: PCI bus 0 slot 16: probe...completed console: PCI bus 0 slot 17: probe...completed console: PCI bus 0 slot 18: probe...completed console: PCI bus 0 slot 19: probe...completed console: PCI bus 0 slot 20: probe...completed console: PCI bus 0 slot 21: probe...completed console: PCI bus 0 slot 22: probe...completed console: PCI bus 0 slot 23: probe...completed console: PCI bus 0 slot 24: probe...completed console: PCI bus 0 slot 25: probe...completed console: PCI bus 0 slot 26: probe...completed console: PCI bus 0 slot 27: probe...completed console: PCI bus 0 slot 28: probe...completed console: PCI bus 0 slot 29: probe...completed console: PCI bus 0 slot 30: probe...completed console: PCI bus 0 slot 31: probe...completed console: PCIS console: PCIR console: PCIW console: PCI bus 0 slot 2/0: mem @0x40000000, reg 0x30 262144 bytes console: PCI bus 0 slot 2/0: mem @0x40040000, reg 0x20 16384 bytes console: PCI bus 0 slot 2/0: mem @0x40044000, reg 0x14 4096 bytes console: PCI bus 0 slot 1/0: mem @0x40045000, reg 0x10 256 bytes console: PCI bus 0 slot 2/0: exp @0x40000000, 262144 bytes console: PCI bus 0 slot 2/0: i/o @0x00004000, reg 0x10 32 bytes console: NETI console: RTCL console: PCID console: VGAI console: memorysize=c000000,base=8f6ff508,sysMem=8f6ef500 console: in setup_int_vect!done!VESA console: vga bios init failed, rc=-1 console: in configure console: mainbus0 (root) console: localbus0 at mainbus0 console: loopdev0 at mainbus0pcibr0 at mainbus0 console: pci0 at pcibr0 bus 0 console: ohci0 at pci0 dev 1 function 0 vendor/product: 0x106b/0x003f (serialbus, USB, interface: 0x10, revision: 0x00)usb base addr : 0xc0045000, bus_base is : 0xc0000000 console: OHCI revision: 0x00000010 console: RH: a: 0x00000203 b: 0x00000000 console: early period(0x0) console: OHCI 8c01ec00 initialized ok console: New Device 0 console: usb_get_descriptor console: bLength = 12 console: bDescriptorType =1 console: bcdUSB = 110 console: bDeviceClass =9 console: bDeviceSubClass =0 console: bDeviceProtocol =0 console: bMaxPacketSize0 =8 console: set address 1 console: usb_get_descriptor console: bLength = 12 console: bDescriptorType =1 console: bcdUSB = 110 console: bDeviceClass =9 console: bDeviceSubClass =0 console: bDeviceProtocol =0 console: bMaxPacketSize0 =8 console: idVendor =0 console: idProduct =0 console: bcdDevice =0 console: iManufacturer=0 console: iProduct =1 console: iSerialNumber=0 console: bNumConfigurations=1 console: usb_get_descriptor console: usb_get_descriptor console: get_conf_no 0 Result 25, wLength 25 console: if 0, ep 0 console: bLength=9 console: bDescriptorType=2 console: wTotalLength=19 console: bNumInterfaces=1 console: bConfigurationValue=1 console: iConfiguration=0 console: bmAttributes=40 console: MaxPower=0 console: 09 04 00 00 01 09 00 00 00 07 05 81 03 02 00 ff console: ##EP epmaxpacketin[1] = 2 console: set configuration 1 console: new device strings: Mfr=0, Product=1, SerialNumber=0 console: USB device number 1 default language ID 0x409 console: Manufacturer console: Product OHCI Root Hub console: SerialNumber console: New Device 1 console: usb_get_descriptor console: bLength = 12 console: bDescriptorType =1 console: bcdUSB = 200 console: bDeviceClass =0 console: bDeviceSubClass =0 console: bDeviceProtocol =0 console: bMaxPacketSize0 =8 console: set address 2 console: usb_get_descriptor console: bLength = 12 console: bDescriptorType =1 console: bcdUSB = 200 console: bDeviceClass =0 console: bDeviceSubClass =0 console: bDeviceProtocol =0 console: bMaxPacketSize0 =8 console: idVendor =627 console: idProduct =1 console: bcdDevice =0 console: iManufacturer=1 console: iProduct =4 console: iSerialNumber=b console: bNumConfigurations=1 console: usb_get_descriptor console: usb_get_descriptor console: get_conf_no 0 Result 34, wLength 34 console: unknown Description Type : 21 console: 09 21 11 01 00 01 22 3F 00 console: if 0, ep 0 console: bLength=9 console: bDescriptorType=2 console: wTotalLength=22 console: bNumInterfaces=1 console: bConfigurationValue=1 console: iConfiguration=8 console: bmAttributes=a0 console: MaxPower=32 console: 09 04 00 00 01 03 01 01 00 09 21 11 01 00 01 22 3f 00 07 05 81 03 08 00 0a console: ##EP epmaxpacketin[1] = 8 console: set configuration 1 console: new device strings: Mfr=1, Product=4, SerialNumber=11 console: USB device number 2 default language ID 0x409 console: Manufacturer QEMU console: Product QEMU USB Keyboard console: SerialNumber 68284-0000:00:01.0-1 console: drive at ohci0 devnum 2, Product QEMU USB Keyboard console: not configured console: New Device 2 console: usb_get_descriptor console: bLength = 12 console: bDescriptorType =1 console: bcdUSB = 200 console: bDeviceClass =0 console: bDeviceSubClass =0 console: bDeviceProtocol =0 console: bMaxPacketSize0 =8 console: set address 3 console: usb_get_descriptor console: bLength = 12 console: bDescriptorType =1 console: bcdUSB = 200 console: bDeviceClass =0 console: bDeviceSubClass =0 console: bDeviceProtocol =0 console: bMaxPacketSize0 =8 console: idVendor =627 console: idProduct =1 console: bcdDevice =0 console: iManufacturer=1 console: iProduct =3 console: iSerialNumber=a console: bNumConfigurations=1 console: usb_get_descriptor console: usb_get_descriptor console: get_conf_no 0 Result 34, wLength 34 console: unknown Description Type : 21 console: 09 21 01 00 00 01 22 4A 00 console: if 0, ep 0 console: bLength=9 console: bDescriptorType=2 console: wTotalLength=22 console: bNumInterfaces=1 console: bConfigurationValue=1 console: iConfiguration=7 console: bmAttributes=a0 console: MaxPower=32 console: 09 04 00 00 01 03 00 00 00 09 21 01 00 00 01 22 4a 00 07 05 81 03 08 00 0a console: ##EP epmaxpacketin[1] = 8 console: set configuration 1 console: new device strings: Mfr=1, Product=3, SerialNumber=10 console: USB device number 3 default language ID 0x409 console: Manufacturer QEMU console: Product QEMU USB Tablet console: SerialNumber 28754-0000:00:01.0-2 console: drive at ohci0 devnum 3, Product QEMU USB Tablet console: not configured console: drive at ohci0 devnum 1, Product OHCI Root Hub console: not configured console: vendor/product: 0x1af4/0x1000 (network, ethernet, interface: 0x00, revision: 0x00) at pci0 dev 2 function 0 not configured console: out configure console: Press to set BIOS,waiting for 3 seconds here..... console: devconfig done. console: ifinit done. console: domaininit done. console: init_proc.... console: HSTI console: SYMI console: SBDE console: [[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[ console: [[ [[[[[[[[[ [[[[[ [[[[ [[[[[ [[[[[ [[[[[ [[[[[ [[[[ [[[[[ [[ console: [[ [[[[[[[[ [[[[ [[[ [[[[ [[[ [[[[ [[[[ [[[[ [[[ [[[[ [[[ [[[[ [[[ [[[[ [[ console: [[ [[[[[[[[ [[[[[[ [[[ [[[[[[ [[[ [ [[[ [[[ [[[[[[[[[[[[ [[[[[[[ [[[[[[ [[[ [ [[[ [[ console: [[ [[[[[[[[ [[[[[[ [[[ [[[[[[ [[[ [[ [[ [[[ [[[ [[[[[[[ [[[[ [[[[[[ [[[ [[ [[ [[ console: [[ [[[[[[[[ [[[[[[ [[[ [[[[[[ [[[ [[[ [ [[[ [[[[[ [[[[[[[[[[ [[[ [[[[[[ [[[ [[[ [ [[ console: [[ [[[[[[[[ [[[[ [[[ [[[[ [[[ [[[[ [[[ [[[[ [[[ [[[ [[[[ [[[[ [[[ [[[[ [[ console: [[ [[[[ [[[[[ [[[[ [[[[[ [[[[ [[[[[ [[[[[[ [[[[ [[[[[ [[ console: [[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[2011 Loongson][[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[ console: Configuration [Bonito,EL,NET,SCSI,IDE] console: Version: PMON2000 3.3 (Bonito) #0: Tue Dec 22 01:58:09 UTC 2020 commit b3ece66234adbf7d4e453f0ba4f326c099ac2a76 Author: Jiaxun Yang Date: Tue Dec 22 09:51:10 2020 +0800 . console: Supported loaders [txt, srec, elf, bin] console: Supported filesystems [net, fat, fs, disk, iso9660, socket, tty, ram] console: This software may be redistributed under the BSD copyright. console: Copyright 2000-2002, Opsycon AB, Sweden. console: Copyright 2005, ICT CAS. console: CPU GODSON3 BogoMIPS: 1327 PASS (3.89 s) RESULTS : PASS 1 | ERROR 0 | FAIL 0 | SKIP 0 | WARN 0 | INTERRUPT 0 | CANCEL 0 JOB TIME : 4.38 s Signed-off-by: Jiaxun Yang Tested-by: Philippe Mathieu-Daudé Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20210112020708.62922-1-jiaxun.yang@flygoat.com> [PMD: Set timeout to 60sec, simply test for ''CPU GODSON3 BogoMIPS'] Signed-off-by: Philippe Mathieu-Daudé --- MAINTAINERS | 1 + tests/acceptance/machine_mips_loongson3v.py | 39 +++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 tests/acceptance/machine_mips_loongson3v.py diff --git a/MAINTAINERS b/MAINTAINERS index 5eeba79c5a..ac411c27f9 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1183,6 +1183,7 @@ F: hw/intc/loongson_liointc.c F: hw/mips/loongson3_bootp.c F: hw/mips/loongson3_bootp.h F: hw/mips/loongson3_virt.c +F: tests/acceptance/machine_mips_loongson3v.py Boston M: Paul Burton diff --git a/tests/acceptance/machine_mips_loongson3v.py b/tests/acceptance/machine_mips_loongson3v.py new file mode 100644 index 0000000000..85b131a40f --- /dev/null +++ b/tests/acceptance/machine_mips_loongson3v.py @@ -0,0 +1,39 @@ +# Functional tests for the Generic Loongson-3 Platform. +# +# Copyright (c) 2021 Jiaxun Yang +# +# This work is licensed under the terms of the GNU GPL, version 2 or later. +# See the COPYING file in the top-level directory. +# +# SPDX-License-Identifier: GPL-2.0-or-later + +import os +import time + +from avocado import skipUnless +from avocado_qemu import Test +from avocado_qemu import wait_for_console_pattern + +class MipsLoongson3v(Test): + timeout = 60 + + @skipUnless(os.getenv('AVOCADO_ALLOW_UNTRUSTED_CODE'), 'untrusted code') + def test_pmon_serial_console(self): + """ + :avocado: tags=arch:mips64el + :avocado: tags=endian:little + :avocado: tags=machine:loongson3-virt + :avocado: tags=cpu:Loongson-3A1000 + :avocado: tags=device:liointc + :avocado: tags=device:goldfish_rtc + """ + + pmon_hash = '7c8b45dd81ccfc55ff28f5aa267a41c3' + pmon_path = self.fetch_asset('https://github.com/loongson-community/pmon/' + 'releases/download/20210112/pmon-3avirt.bin', + asset_hash=pmon_hash, algorithm='md5') + + self.vm.set_console() + self.vm.add_args('-bios', pmon_path) + self.vm.launch() + wait_for_console_pattern(self, 'CPU GODSON3 BogoMIPS:') -- cgit v1.2.3-55-g7522 From 0ab8e33a48414e094e74bcc48b0914325def85ac Mon Sep 17 00:00:00 2001 From: Philippe Mathieu-Daudé Date: Sat, 16 Jan 2021 18:52:00 +0100 Subject: target/mips: fetch code with translator_ld Similarly to commits ae82adc8e29..7f93879e444, use the translator_ld*() API introduced in commit 409c1a0bf0f to fetch the code on the MIPS target. Reviewed-by: Jiaxun Yang Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Reviewed-by: Alex Bennée Message-Id: <20210125105818.2707067-1-f4bug@amsat.org> --- target/mips/translate.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/target/mips/translate.c b/target/mips/translate.c index a5cf1742a8..a6e835809a 100644 --- a/target/mips/translate.c +++ b/target/mips/translate.c @@ -26,7 +26,7 @@ #include "cpu.h" #include "internal.h" #include "tcg/tcg-op.h" -#include "exec/cpu_ldst.h" +#include "exec/translator.h" #include "exec/helper-proto.h" #include "exec/helper-gen.h" #include "hw/semihosting/semihost.h" @@ -13911,7 +13911,7 @@ static void decode_i64_mips16(DisasContext *ctx, static int decode_extended_mips16_opc(CPUMIPSState *env, DisasContext *ctx) { - int extend = cpu_lduw_code(env, ctx->base.pc_next + 2); + int extend = translator_lduw(env, ctx->base.pc_next + 2); int op, rx, ry, funct, sa; int16_t imm, offset; @@ -14161,7 +14161,7 @@ static int decode_mips16_opc(CPUMIPSState *env, DisasContext *ctx) /* No delay slot, so just process as a normal instruction */ break; case M16_OPC_JAL: - offset = cpu_lduw_code(env, ctx->base.pc_next + 2); + offset = translator_lduw(env, ctx->base.pc_next + 2); offset = (((ctx->opcode & 0x1f) << 21) | ((ctx->opcode >> 5) & 0x1f) << 16 | offset) << 2; @@ -16295,7 +16295,7 @@ static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx) uint32_t op, minor, minor2, mips32_op; uint32_t cond, fmt, cc; - insn = cpu_lduw_code(env, ctx->base.pc_next + 2); + insn = translator_lduw(env, ctx->base.pc_next + 2); ctx->opcode = (ctx->opcode << 16) | insn; rt = (ctx->opcode >> 21) & 0x1f; @@ -21350,7 +21350,7 @@ static int decode_nanomips_32_48_opc(CPUMIPSState *env, DisasContext *ctx) int offset; int imm; - insn = cpu_lduw_code(env, ctx->base.pc_next + 2); + insn = translator_lduw(env, ctx->base.pc_next + 2); ctx->opcode = (ctx->opcode << 16) | insn; rt = extract32(ctx->opcode, 21, 5); @@ -21469,7 +21469,7 @@ static int decode_nanomips_32_48_opc(CPUMIPSState *env, DisasContext *ctx) break; case NM_P48I: { - insn = cpu_lduw_code(env, ctx->base.pc_next + 4); + insn = translator_lduw(env, ctx->base.pc_next + 4); target_long addr_off = extract32(ctx->opcode, 0, 16) | insn << 16; switch (extract32(ctx->opcode, 16, 5)) { case NM_LI48: @@ -29087,17 +29087,17 @@ static void mips_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) is_slot = ctx->hflags & MIPS_HFLAG_BMASK; if (ctx->insn_flags & ISA_NANOMIPS32) { - ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next); + ctx->opcode = translator_lduw(env, ctx->base.pc_next); insn_bytes = decode_nanomips_opc(env, ctx); } else if (!(ctx->hflags & MIPS_HFLAG_M16)) { - ctx->opcode = cpu_ldl_code(env, ctx->base.pc_next); + ctx->opcode = translator_ldl(env, ctx->base.pc_next); insn_bytes = 4; decode_opc(env, ctx); } else if (ctx->insn_flags & ASE_MICROMIPS) { - ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next); + ctx->opcode = translator_lduw(env, ctx->base.pc_next); insn_bytes = decode_micromips_opc(env, ctx); } else if (ctx->insn_flags & ASE_MIPS16) { - ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next); + ctx->opcode = translator_lduw(env, ctx->base.pc_next); insn_bytes = decode_mips16_opc(env, ctx); } else { gen_reserved_instruction(ctx); -- cgit v1.2.3-55-g7522 From afe2fe4d04d3b260c1802adb59d851905f3bcb3c Mon Sep 17 00:00:00 2001 From: Philippe Mathieu-Daudé Date: Thu, 28 Jan 2021 01:43:34 +0100 Subject: target/mips: Remove access_type argument from map_address() handler TLB map_address() handlers don't use the 'access_type' argument, remove it to simplify. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Reviewed-by: Jiaxun Yang Message-Id: <20210128144125.3696119-2-f4bug@amsat.org> --- target/mips/internal.h | 8 ++++---- target/mips/tlb_helper.c | 15 +++++++-------- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/target/mips/internal.h b/target/mips/internal.h index 5dd17ff733..d09afded5e 100644 --- a/target/mips/internal.h +++ b/target/mips/internal.h @@ -111,7 +111,7 @@ struct CPUMIPSTLBContext { uint32_t nb_tlb; uint32_t tlb_in_use; int (*map_address)(struct CPUMIPSState *env, hwaddr *physical, int *prot, - target_ulong address, int rw, int access_type); + target_ulong address, int rw); void (*helper_tlbwi)(struct CPUMIPSState *env); void (*helper_tlbwr)(struct CPUMIPSState *env); void (*helper_tlbp)(struct CPUMIPSState *env); @@ -126,11 +126,11 @@ struct CPUMIPSTLBContext { }; int no_mmu_map_address(CPUMIPSState *env, hwaddr *physical, int *prot, - target_ulong address, int rw, int access_type); + target_ulong address, int rw); int fixed_mmu_map_address(CPUMIPSState *env, hwaddr *physical, int *prot, - target_ulong address, int rw, int access_type); + target_ulong address, int rw); int r4k_map_address(CPUMIPSState *env, hwaddr *physical, int *prot, - target_ulong address, int rw, int access_type); + target_ulong address, int rw); void r4k_helper_tlbwi(CPUMIPSState *env); void r4k_helper_tlbwr(CPUMIPSState *env); void r4k_helper_tlbp(CPUMIPSState *env); diff --git a/target/mips/tlb_helper.c b/target/mips/tlb_helper.c index 082c17928d..1af2dc969d 100644 --- a/target/mips/tlb_helper.c +++ b/target/mips/tlb_helper.c @@ -39,7 +39,7 @@ enum { /* no MMU emulation */ int no_mmu_map_address(CPUMIPSState *env, hwaddr *physical, int *prot, - target_ulong address, int rw, int access_type) + target_ulong address, int rw) { *physical = address; *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC; @@ -48,7 +48,7 @@ int no_mmu_map_address(CPUMIPSState *env, hwaddr *physical, int *prot, /* fixed mapping MMU emulation */ int fixed_mmu_map_address(CPUMIPSState *env, hwaddr *physical, int *prot, - target_ulong address, int rw, int access_type) + target_ulong address, int rw) { if (address <= (int32_t)0x7FFFFFFFUL) { if (!(env->CP0_Status & (1 << CP0St_ERL))) { @@ -68,7 +68,7 @@ int fixed_mmu_map_address(CPUMIPSState *env, hwaddr *physical, int *prot, /* MIPS32/MIPS64 R4000-style MMU emulation */ int r4k_map_address(CPUMIPSState *env, hwaddr *physical, int *prot, - target_ulong address, int rw, int access_type) + target_ulong address, int rw) { uint16_t ASID = env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask; uint32_t MMID = env->CP0_MemoryMapID; @@ -234,8 +234,7 @@ static int get_seg_physical_address(CPUMIPSState *env, hwaddr *physical, return mapped; } else if (mapped) { /* The segment is TLB mapped */ - return env->tlb->map_address(env, physical, prot, real_address, rw, - access_type); + return env->tlb->map_address(env, physical, prot, real_address, rw); } else { /* The segment is unmapped */ *physical = physical_base | (real_address & segmask); @@ -314,7 +313,7 @@ static int get_physical_address(CPUMIPSState *env, hwaddr *physical, /* xuseg */ if (UX && address <= (0x3FFFFFFFFFFFFFFFULL & env->SEGMask)) { ret = env->tlb->map_address(env, physical, prot, - real_address, rw, access_type); + real_address, rw); } else { ret = TLBRET_BADADDR; } @@ -323,7 +322,7 @@ static int get_physical_address(CPUMIPSState *env, hwaddr *physical, if ((supervisor_mode || kernel_mode) && SX && address <= (0x7FFFFFFFFFFFFFFFULL & env->SEGMask)) { ret = env->tlb->map_address(env, physical, prot, - real_address, rw, access_type); + real_address, rw); } else { ret = TLBRET_BADADDR; } @@ -364,7 +363,7 @@ static int get_physical_address(CPUMIPSState *env, hwaddr *physical, if (kernel_mode && KX && address <= (0xFFFFFFFF7FFFFFFFULL & env->SEGMask)) { ret = env->tlb->map_address(env, physical, prot, - real_address, rw, access_type); + real_address, rw); } else { ret = TLBRET_BADADDR; } -- cgit v1.2.3-55-g7522 From 496892282520d7e55ce3b48b7cdc772199a44ad4 Mon Sep 17 00:00:00 2001 From: Philippe Mathieu-Daudé Date: Thu, 28 Jan 2021 01:48:28 +0100 Subject: target/mips: Remove access_type argument from get_seg_physical_address get_seg_physical_address() doesn't use the 'access_type' argument, remove it to simplify. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Reviewed-by: Jiaxun Yang Message-Id: <20210128144125.3696119-3-f4bug@amsat.org> --- target/mips/tlb_helper.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/target/mips/tlb_helper.c b/target/mips/tlb_helper.c index 1af2dc969d..9906292440 100644 --- a/target/mips/tlb_helper.c +++ b/target/mips/tlb_helper.c @@ -222,7 +222,7 @@ static int is_seg_am_mapped(unsigned int am, bool eu, int mmu_idx) static int get_seg_physical_address(CPUMIPSState *env, hwaddr *physical, int *prot, target_ulong real_address, - int rw, int access_type, int mmu_idx, + int rw, int mmu_idx, unsigned int am, bool eu, target_ulong segmask, hwaddr physical_base) @@ -253,7 +253,7 @@ static int get_segctl_physical_address(CPUMIPSState *env, hwaddr *physical, hwaddr pa = ((hwaddr)segctl & CP0SC_PA_MASK) << 20; return get_seg_physical_address(env, physical, prot, real_address, rw, - access_type, mmu_idx, am, eu, segmask, + mmu_idx, am, eu, segmask, pa & ~(hwaddr)segmask); } @@ -349,7 +349,7 @@ static int get_physical_address(CPUMIPSState *env, hwaddr *physical, /* Does CP0_Status.KX/SX/UX permit the access mode (am) */ if (env->CP0_Status & am_ksux[am]) { ret = get_seg_physical_address(env, physical, prot, - real_address, rw, access_type, + real_address, rw, mmu_idx, am, false, env->PAMask, 0); } else { -- cgit v1.2.3-55-g7522 From 0230a13793b1b30b6b06fd5be1272556a5880ded Mon Sep 17 00:00:00 2001 From: Philippe Mathieu-Daudé Date: Thu, 28 Jan 2021 01:50:06 +0100 Subject: target/mips: Remove access_type arg from get_segctl_physical_address() get_segctl_physical_address() doesn't use the 'access_type' argument, remove it to simplify. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Reviewed-by: Jiaxun Yang Message-Id: <20210128144125.3696119-4-f4bug@amsat.org> --- target/mips/tlb_helper.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/target/mips/tlb_helper.c b/target/mips/tlb_helper.c index 9906292440..d89ad87cb9 100644 --- a/target/mips/tlb_helper.c +++ b/target/mips/tlb_helper.c @@ -245,7 +245,7 @@ static int get_seg_physical_address(CPUMIPSState *env, hwaddr *physical, static int get_segctl_physical_address(CPUMIPSState *env, hwaddr *physical, int *prot, target_ulong real_address, - int rw, int access_type, int mmu_idx, + int rw, int mmu_idx, uint16_t segctl, target_ulong segmask) { unsigned int am = (segctl & CP0SC_AM_MASK) >> CP0SC_AM; @@ -306,7 +306,7 @@ static int get_physical_address(CPUMIPSState *env, hwaddr *physical, segctl = env->CP0_SegCtl2 >> 16; } ret = get_segctl_physical_address(env, physical, prot, - real_address, rw, access_type, + real_address, rw, mmu_idx, segctl, 0x3FFFFFFF); #if defined(TARGET_MIPS64) } else if (address < 0x4000000000000000ULL) { @@ -370,26 +370,26 @@ static int get_physical_address(CPUMIPSState *env, hwaddr *physical, #endif } else if (address < KSEG1_BASE) { /* kseg0 */ - ret = get_segctl_physical_address(env, physical, prot, real_address, rw, - access_type, mmu_idx, + ret = get_segctl_physical_address(env, physical, prot, real_address, + rw, mmu_idx, env->CP0_SegCtl1 >> 16, 0x1FFFFFFF); } else if (address < KSEG2_BASE) { /* kseg1 */ - ret = get_segctl_physical_address(env, physical, prot, real_address, rw, - access_type, mmu_idx, + ret = get_segctl_physical_address(env, physical, prot, real_address, + rw, mmu_idx, env->CP0_SegCtl1, 0x1FFFFFFF); } else if (address < KSEG3_BASE) { /* sseg (kseg2) */ - ret = get_segctl_physical_address(env, physical, prot, real_address, rw, - access_type, mmu_idx, + ret = get_segctl_physical_address(env, physical, prot, real_address, + rw, mmu_idx, env->CP0_SegCtl0 >> 16, 0x1FFFFFFF); } else { /* * kseg3 * XXX: debug segment is not emulated */ - ret = get_segctl_physical_address(env, physical, prot, real_address, rw, - access_type, mmu_idx, + ret = get_segctl_physical_address(env, physical, prot, real_address, + rw, mmu_idx, env->CP0_SegCtl0, 0x1FFFFFFF); } return ret; -- cgit v1.2.3-55-g7522 From 935c103490eb628dfd6166819ddbbbde87285e69 Mon Sep 17 00:00:00 2001 From: Philippe Mathieu-Daudé Date: Thu, 28 Jan 2021 01:52:56 +0100 Subject: target/mips: Remove access_type argument from get_physical_address() get_physical_address() doesn't use the 'access_type' argument, remove it to simplify. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Reviewed-by: Jiaxun Yang Message-Id: <20210128144125.3696119-5-f4bug@amsat.org> --- target/mips/tlb_helper.c | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/target/mips/tlb_helper.c b/target/mips/tlb_helper.c index d89ad87cb9..c9535b7f72 100644 --- a/target/mips/tlb_helper.c +++ b/target/mips/tlb_helper.c @@ -259,7 +259,7 @@ static int get_segctl_physical_address(CPUMIPSState *env, hwaddr *physical, static int get_physical_address(CPUMIPSState *env, hwaddr *physical, int *prot, target_ulong real_address, - int rw, int access_type, int mmu_idx) + int rw, int mmu_idx) { /* User mode can only access useg/xuseg */ #if defined(TARGET_MIPS64) @@ -492,7 +492,7 @@ hwaddr mips_cpu_get_phys_page_debug(CPUState *cs, vaddr addr) hwaddr phys_addr; int prot; - if (get_physical_address(env, &phys_addr, &prot, addr, 0, ACCESS_INT, + if (get_physical_address(env, &phys_addr, &prot, addr, 0, cpu_mmu_index(env, false)) != 0) { return -1; } @@ -570,7 +570,7 @@ static int walk_directory(CPUMIPSState *env, uint64_t *vaddr, uint64_t w = 0; if (get_physical_address(env, &paddr, &prot, *vaddr, MMU_DATA_LOAD, - ACCESS_INT, cpu_mmu_index(env, false)) != + cpu_mmu_index(env, false)) != TLBRET_MATCH) { /* wrong base address */ return 0; @@ -598,7 +598,7 @@ static int walk_directory(CPUMIPSState *env, uint64_t *vaddr, *pw_entrylo0 = entry; } if (get_physical_address(env, &paddr, &prot, vaddr2, MMU_DATA_LOAD, - ACCESS_INT, cpu_mmu_index(env, false)) != + cpu_mmu_index(env, false)) != TLBRET_MATCH) { return 0; } @@ -752,7 +752,7 @@ static bool page_table_walk_refill(CPUMIPSState *env, vaddr address, int rw, /* Leaf Level Page Table - First half of PTE pair */ vaddr |= ptoffset0; if (get_physical_address(env, &paddr, &prot, vaddr, MMU_DATA_LOAD, - ACCESS_INT, cpu_mmu_index(env, false)) != + cpu_mmu_index(env, false)) != TLBRET_MATCH) { return false; } @@ -765,7 +765,7 @@ static bool page_table_walk_refill(CPUMIPSState *env, vaddr address, int rw, /* Leaf Level Page Table - Second half of PTE pair */ vaddr |= ptoffset1; if (get_physical_address(env, &paddr, &prot, vaddr, MMU_DATA_LOAD, - ACCESS_INT, cpu_mmu_index(env, false)) != + cpu_mmu_index(env, false)) != TLBRET_MATCH) { return false; } @@ -843,16 +843,14 @@ bool mips_cpu_tlb_fill(CPUState *cs, vaddr address, int size, #if !defined(CONFIG_USER_ONLY) hwaddr physical; int prot; - int mips_access_type; #endif int ret = TLBRET_BADADDR; /* data access */ #if !defined(CONFIG_USER_ONLY) /* XXX: put correct access by using cpu_restore_state() correctly */ - mips_access_type = ACCESS_INT; ret = get_physical_address(env, &physical, &prot, address, - access_type, mips_access_type, mmu_idx); + access_type, mmu_idx); switch (ret) { case TLBRET_MATCH: qemu_log_mask(CPU_LOG_MMU, @@ -884,7 +882,7 @@ bool mips_cpu_tlb_fill(CPUState *cs, vaddr address, int size, env->hflags |= mode; if (ret_walker) { ret = get_physical_address(env, &physical, &prot, address, - access_type, mips_access_type, mmu_idx); + access_type, mmu_idx); if (ret == TLBRET_MATCH) { tlb_set_page(cs, address & TARGET_PAGE_MASK, physical & TARGET_PAGE_MASK, prot, @@ -909,12 +907,10 @@ hwaddr cpu_mips_translate_address(CPUMIPSState *env, target_ulong address, { hwaddr physical; int prot; - int access_type; int ret = 0; /* data access */ - access_type = ACCESS_INT; - ret = get_physical_address(env, &physical, &prot, address, rw, access_type, + ret = get_physical_address(env, &physical, &prot, address, rw, cpu_mmu_index(env, false)); if (ret != TLBRET_MATCH) { raise_mmu_exception(env, address, rw, ret); -- cgit v1.2.3-55-g7522 From e78d4ab6aae78c3de2eb324e4dc484ece2f8f090 Mon Sep 17 00:00:00 2001 From: Philippe Mathieu-Daudé Date: Thu, 28 Jan 2021 01:53:44 +0100 Subject: target/mips: Remove unused MMU definitions Remove these confusing and unused definitions. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Reviewed-by: Jiaxun Yang Message-Id: <20210128144125.3696119-6-f4bug@amsat.org> --- target/mips/cpu.h | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/target/mips/cpu.h b/target/mips/cpu.h index b9e227a30e..9e6028f8e6 100644 --- a/target/mips/cpu.h +++ b/target/mips/cpu.h @@ -1220,22 +1220,6 @@ typedef MIPSCPU ArchCPU; #include "exec/cpu-all.h" -/* - * Memory access type : - * may be needed for precise access rights control and precise exceptions. - */ -enum { - /* 1 bit to define user level / supervisor access */ - ACCESS_USER = 0x00, - ACCESS_SUPER = 0x01, - /* 1 bit to indicate direction */ - ACCESS_STORE = 0x02, - /* Type of instruction that generated the access */ - ACCESS_CODE = 0x10, /* Code fetch access */ - ACCESS_INT = 0x20, /* Integer load/store access */ - ACCESS_FLOAT = 0x30, /* floating point load/store access */ -}; - /* Exceptions */ enum { EXCP_NONE = -1, -- cgit v1.2.3-55-g7522 From fd305527e3b2dd66240ba2fede5ca3709aeb2392 Mon Sep 17 00:00:00 2001 From: Philippe Mathieu-Daudé Date: Thu, 28 Jan 2021 01:54:52 +0100 Subject: target/mips: Replace magic value by MMU_DATA_LOAD definition Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Reviewed-by: Jiaxun Yang Message-Id: <20210128144125.3696119-7-f4bug@amsat.org> --- target/mips/op_helper.c | 2 +- target/mips/tlb_helper.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/target/mips/op_helper.c b/target/mips/op_helper.c index 89c7d4556a..9fce0194b3 100644 --- a/target/mips/op_helper.c +++ b/target/mips/op_helper.c @@ -312,7 +312,7 @@ target_ulong helper_##name(CPUMIPSState *env, target_ulong arg, int mem_idx) \ } \ do_raise_exception(env, EXCP_AdEL, GETPC()); \ } \ - env->CP0_LLAddr = do_translate_address(env, arg, 0, GETPC()); \ + env->CP0_LLAddr = do_translate_address(env, arg, MMU_DATA_LOAD, GETPC()); \ env->lladdr = arg; \ env->llval = do_cast cpu_##insn##_mmuidx_ra(env, arg, mem_idx, GETPC()); \ return env->llval; \ diff --git a/target/mips/tlb_helper.c b/target/mips/tlb_helper.c index c9535b7f72..9216c7a91b 100644 --- a/target/mips/tlb_helper.c +++ b/target/mips/tlb_helper.c @@ -492,7 +492,7 @@ hwaddr mips_cpu_get_phys_page_debug(CPUState *cs, vaddr addr) hwaddr phys_addr; int prot; - if (get_physical_address(env, &phys_addr, &prot, addr, 0, + if (get_physical_address(env, &phys_addr, &prot, addr, MMU_DATA_LOAD, cpu_mmu_index(env, false)) != 0) { return -1; } -- cgit v1.2.3-55-g7522 From 1190c53e822a287f2767ebddf792d290dd760db0 Mon Sep 17 00:00:00 2001 From: Philippe Mathieu-Daudé Date: Thu, 28 Jan 2021 02:07:09 +0100 Subject: target/mips: Let do_translate_address() take MMUAccessType argument The single caller, HELPER_LD_ATOMIC(), passes MMUAccessType to do_translate_address(). Let the prototype use it as argument, as it is stricter than an integer. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Reviewed-by: Jiaxun Yang Message-Id: <20210128144125.3696119-9-f4bug@amsat.org> --- target/mips/op_helper.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/target/mips/op_helper.c b/target/mips/op_helper.c index 9fce0194b3..b80e8f7540 100644 --- a/target/mips/op_helper.c +++ b/target/mips/op_helper.c @@ -288,13 +288,14 @@ target_ulong helper_rotx(target_ulong rs, uint32_t shift, uint32_t shiftx, #ifndef CONFIG_USER_ONLY static inline hwaddr do_translate_address(CPUMIPSState *env, - target_ulong address, - int rw, uintptr_t retaddr) + target_ulong address, + MMUAccessType access_type, + uintptr_t retaddr) { hwaddr paddr; CPUState *cs = env_cpu(env); - paddr = cpu_mips_translate_address(env, address, rw); + paddr = cpu_mips_translate_address(env, address, access_type); if (paddr == -1LL) { cpu_loop_exit_restore(cs, retaddr); -- cgit v1.2.3-55-g7522 From 48b28c6a8e9ff64498efa244b1b3ee1bbcd01202 Mon Sep 17 00:00:00 2001 From: Philippe Mathieu-Daudé Date: Thu, 28 Jan 2021 02:08:39 +0100 Subject: target/mips: Let cpu_mips_translate_address() take MMUAccessType arg The single caller, do_translate_address(), passes MMUAccessType to cpu_mips_translate_address(). Let the prototype use it as argument, as it is stricter than an integer. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Reviewed-by: Jiaxun Yang Message-Id: <20210128144125.3696119-10-f4bug@amsat.org> --- target/mips/internal.h | 2 +- target/mips/tlb_helper.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/target/mips/internal.h b/target/mips/internal.h index d09afded5e..34915c275c 100644 --- a/target/mips/internal.h +++ b/target/mips/internal.h @@ -146,7 +146,7 @@ void mips_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr, int mmu_idx, MemTxAttrs attrs, MemTxResult response, uintptr_t retaddr); hwaddr cpu_mips_translate_address(CPUMIPSState *env, target_ulong address, - int rw); + MMUAccessType access_type); #endif #define cpu_signal_handler cpu_mips_signal_handler diff --git a/target/mips/tlb_helper.c b/target/mips/tlb_helper.c index 9216c7a91b..9bb635885d 100644 --- a/target/mips/tlb_helper.c +++ b/target/mips/tlb_helper.c @@ -903,17 +903,17 @@ bool mips_cpu_tlb_fill(CPUState *cs, vaddr address, int size, #ifndef CONFIG_USER_ONLY hwaddr cpu_mips_translate_address(CPUMIPSState *env, target_ulong address, - int rw) + MMUAccessType access_type) { hwaddr physical; int prot; int ret = 0; /* data access */ - ret = get_physical_address(env, &physical, &prot, address, rw, + ret = get_physical_address(env, &physical, &prot, address, access_type, cpu_mmu_index(env, false)); if (ret != TLBRET_MATCH) { - raise_mmu_exception(env, address, rw, ret); + raise_mmu_exception(env, address, access_type, ret); return -1LL; } else { return physical; -- cgit v1.2.3-55-g7522 From ca354f00047a1065a43286debbb8ead0a6d0fe08 Mon Sep 17 00:00:00 2001 From: Philippe Mathieu-Daudé Date: Thu, 28 Jan 2021 02:09:18 +0100 Subject: target/mips: Let raise_mmu_exception() take MMUAccessType argument Both mips_cpu_tlb_fill() and cpu_mips_translate_address() pass MMUAccessType to raise_mmu_exception(). Let the prototype use it as argument, as it is stricter than an integer. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Reviewed-by: Jiaxun Yang Message-Id: <20210128144125.3696119-11-f4bug@amsat.org> --- target/mips/tlb_helper.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/target/mips/tlb_helper.c b/target/mips/tlb_helper.c index 9bb635885d..0ad2d51b11 100644 --- a/target/mips/tlb_helper.c +++ b/target/mips/tlb_helper.c @@ -405,12 +405,12 @@ void cpu_mips_tlb_flush(CPUMIPSState *env) #endif /* !CONFIG_USER_ONLY */ static void raise_mmu_exception(CPUMIPSState *env, target_ulong address, - int rw, int tlb_error) + MMUAccessType access_type, int tlb_error) { CPUState *cs = env_cpu(env); int exception = 0, error_code = 0; - if (rw == MMU_INST_FETCH) { + if (access_type == MMU_INST_FETCH) { error_code |= EXCP_INST_NOTAVAIL; } @@ -419,7 +419,7 @@ static void raise_mmu_exception(CPUMIPSState *env, target_ulong address, case TLBRET_BADADDR: /* Reference to kernel address from user mode or supervisor mode */ /* Reference to supervisor address from user mode */ - if (rw == MMU_DATA_STORE) { + if (access_type == MMU_DATA_STORE) { exception = EXCP_AdES; } else { exception = EXCP_AdEL; @@ -427,7 +427,7 @@ static void raise_mmu_exception(CPUMIPSState *env, target_ulong address, break; case TLBRET_NOMATCH: /* No TLB match for a mapped address */ - if (rw == MMU_DATA_STORE) { + if (access_type == MMU_DATA_STORE) { exception = EXCP_TLBS; } else { exception = EXCP_TLBL; @@ -436,7 +436,7 @@ static void raise_mmu_exception(CPUMIPSState *env, target_ulong address, break; case TLBRET_INVALID: /* TLB match with no valid bit */ - if (rw == MMU_DATA_STORE) { + if (access_type == MMU_DATA_STORE) { exception = EXCP_TLBS; } else { exception = EXCP_TLBL; -- cgit v1.2.3-55-g7522 From 7c6e2049f099e1bbdbf9dbc219be963d1ff509c0 Mon Sep 17 00:00:00 2001 From: Philippe Mathieu-Daudé Date: Thu, 28 Jan 2021 02:09:49 +0100 Subject: target/mips: Let get_physical_address() take MMUAccessType argument All these functions: - mips_cpu_get_phys_page_debug() - cpu_mips_translate_address() - mips_cpu_tlb_fill() - page_table_walk_refill() - walk_directory() call get_physical_address() passing a MMUAccessType type. Let the prototype use it as argument, as it is stricter than an integer. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Reviewed-by: Jiaxun Yang Message-Id: <20210128144125.3696119-12-f4bug@amsat.org> --- target/mips/tlb_helper.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/target/mips/tlb_helper.c b/target/mips/tlb_helper.c index 0ad2d51b11..f15cc48a06 100644 --- a/target/mips/tlb_helper.c +++ b/target/mips/tlb_helper.c @@ -259,7 +259,7 @@ static int get_segctl_physical_address(CPUMIPSState *env, hwaddr *physical, static int get_physical_address(CPUMIPSState *env, hwaddr *physical, int *prot, target_ulong real_address, - int rw, int mmu_idx) + MMUAccessType access_type, int mmu_idx) { /* User mode can only access useg/xuseg */ #if defined(TARGET_MIPS64) @@ -306,14 +306,14 @@ static int get_physical_address(CPUMIPSState *env, hwaddr *physical, segctl = env->CP0_SegCtl2 >> 16; } ret = get_segctl_physical_address(env, physical, prot, - real_address, rw, + real_address, access_type, mmu_idx, segctl, 0x3FFFFFFF); #if defined(TARGET_MIPS64) } else if (address < 0x4000000000000000ULL) { /* xuseg */ if (UX && address <= (0x3FFFFFFFFFFFFFFFULL & env->SEGMask)) { ret = env->tlb->map_address(env, physical, prot, - real_address, rw); + real_address, access_type); } else { ret = TLBRET_BADADDR; } @@ -322,7 +322,7 @@ static int get_physical_address(CPUMIPSState *env, hwaddr *physical, if ((supervisor_mode || kernel_mode) && SX && address <= (0x7FFFFFFFFFFFFFFFULL & env->SEGMask)) { ret = env->tlb->map_address(env, physical, prot, - real_address, rw); + real_address, access_type); } else { ret = TLBRET_BADADDR; } @@ -349,7 +349,7 @@ static int get_physical_address(CPUMIPSState *env, hwaddr *physical, /* Does CP0_Status.KX/SX/UX permit the access mode (am) */ if (env->CP0_Status & am_ksux[am]) { ret = get_seg_physical_address(env, physical, prot, - real_address, rw, + real_address, access_type, mmu_idx, am, false, env->PAMask, 0); } else { @@ -363,7 +363,7 @@ static int get_physical_address(CPUMIPSState *env, hwaddr *physical, if (kernel_mode && KX && address <= (0xFFFFFFFF7FFFFFFFULL & env->SEGMask)) { ret = env->tlb->map_address(env, physical, prot, - real_address, rw); + real_address, access_type); } else { ret = TLBRET_BADADDR; } @@ -371,17 +371,17 @@ static int get_physical_address(CPUMIPSState *env, hwaddr *physical, } else if (address < KSEG1_BASE) { /* kseg0 */ ret = get_segctl_physical_address(env, physical, prot, real_address, - rw, mmu_idx, + access_type, mmu_idx, env->CP0_SegCtl1 >> 16, 0x1FFFFFFF); } else if (address < KSEG2_BASE) { /* kseg1 */ ret = get_segctl_physical_address(env, physical, prot, real_address, - rw, mmu_idx, + access_type, mmu_idx, env->CP0_SegCtl1, 0x1FFFFFFF); } else if (address < KSEG3_BASE) { /* sseg (kseg2) */ ret = get_segctl_physical_address(env, physical, prot, real_address, - rw, mmu_idx, + access_type, mmu_idx, env->CP0_SegCtl0 >> 16, 0x1FFFFFFF); } else { /* @@ -389,7 +389,7 @@ static int get_physical_address(CPUMIPSState *env, hwaddr *physical, * XXX: debug segment is not emulated */ ret = get_segctl_physical_address(env, physical, prot, real_address, - rw, mmu_idx, + access_type, mmu_idx, env->CP0_SegCtl0, 0x1FFFFFFF); } return ret; -- cgit v1.2.3-55-g7522 From 67b663d6fadaa4755bd9e1263deb36122c2e05b9 Mon Sep 17 00:00:00 2001 From: Philippe Mathieu-Daudé Date: Thu, 28 Jan 2021 02:10:54 +0100 Subject: target/mips: Let get_seg*_physical_address() take MMUAccessType arg get_physical_address() calls get_seg_physical_address() and get_segctl_physical_address() passing a MMUAccessType type. Let the prototypes use it as argument, as it is stricter than an integer. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Reviewed-by: Jiaxun Yang Message-Id: <20210128144125.3696119-13-f4bug@amsat.org> --- target/mips/tlb_helper.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/target/mips/tlb_helper.c b/target/mips/tlb_helper.c index f15cc48a06..4db8a7582d 100644 --- a/target/mips/tlb_helper.c +++ b/target/mips/tlb_helper.c @@ -222,7 +222,7 @@ static int is_seg_am_mapped(unsigned int am, bool eu, int mmu_idx) static int get_seg_physical_address(CPUMIPSState *env, hwaddr *physical, int *prot, target_ulong real_address, - int rw, int mmu_idx, + MMUAccessType access_type, int mmu_idx, unsigned int am, bool eu, target_ulong segmask, hwaddr physical_base) @@ -234,7 +234,8 @@ static int get_seg_physical_address(CPUMIPSState *env, hwaddr *physical, return mapped; } else if (mapped) { /* The segment is TLB mapped */ - return env->tlb->map_address(env, physical, prot, real_address, rw); + return env->tlb->map_address(env, physical, prot, real_address, + access_type); } else { /* The segment is unmapped */ *physical = physical_base | (real_address & segmask); @@ -245,15 +246,15 @@ static int get_seg_physical_address(CPUMIPSState *env, hwaddr *physical, static int get_segctl_physical_address(CPUMIPSState *env, hwaddr *physical, int *prot, target_ulong real_address, - int rw, int mmu_idx, + MMUAccessType access_type, int mmu_idx, uint16_t segctl, target_ulong segmask) { unsigned int am = (segctl & CP0SC_AM_MASK) >> CP0SC_AM; bool eu = (segctl >> CP0SC_EU) & 1; hwaddr pa = ((hwaddr)segctl & CP0SC_PA_MASK) << 20; - return get_seg_physical_address(env, physical, prot, real_address, rw, - mmu_idx, am, eu, segmask, + return get_seg_physical_address(env, physical, prot, real_address, + access_type, mmu_idx, am, eu, segmask, pa & ~(hwaddr)segmask); } -- cgit v1.2.3-55-g7522 From edbd4992fb5d782c858f5196ecb452d61dbc6ab1 Mon Sep 17 00:00:00 2001 From: Philippe Mathieu-Daudé Date: Thu, 28 Jan 2021 02:11:06 +0100 Subject: target/mips: Let CPUMIPSTLBContext::map_address() take MMUAccessType get_seg_physical_address() calls CPUMIPSTLBContext::map_address() handlers passing a MMUAccessType type. Update the prototype handlers to take a MMUAccessType argument, as it is stricter than an integer. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Reviewed-by: Jiaxun Yang Message-Id: <20210128144125.3696119-14-f4bug@amsat.org> --- target/mips/internal.h | 8 ++++---- target/mips/tlb_helper.c | 12 ++++++------ 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/target/mips/internal.h b/target/mips/internal.h index 34915c275c..99264b8bf6 100644 --- a/target/mips/internal.h +++ b/target/mips/internal.h @@ -111,7 +111,7 @@ struct CPUMIPSTLBContext { uint32_t nb_tlb; uint32_t tlb_in_use; int (*map_address)(struct CPUMIPSState *env, hwaddr *physical, int *prot, - target_ulong address, int rw); + target_ulong address, MMUAccessType access_type); void (*helper_tlbwi)(struct CPUMIPSState *env); void (*helper_tlbwr)(struct CPUMIPSState *env); void (*helper_tlbp)(struct CPUMIPSState *env); @@ -126,11 +126,11 @@ struct CPUMIPSTLBContext { }; int no_mmu_map_address(CPUMIPSState *env, hwaddr *physical, int *prot, - target_ulong address, int rw); + target_ulong address, MMUAccessType access_type); int fixed_mmu_map_address(CPUMIPSState *env, hwaddr *physical, int *prot, - target_ulong address, int rw); + target_ulong address, MMUAccessType access_type); int r4k_map_address(CPUMIPSState *env, hwaddr *physical, int *prot, - target_ulong address, int rw); + target_ulong address, MMUAccessType access_type); void r4k_helper_tlbwi(CPUMIPSState *env); void r4k_helper_tlbwr(CPUMIPSState *env); void r4k_helper_tlbp(CPUMIPSState *env); diff --git a/target/mips/tlb_helper.c b/target/mips/tlb_helper.c index 4db8a7582d..b48f892a51 100644 --- a/target/mips/tlb_helper.c +++ b/target/mips/tlb_helper.c @@ -39,7 +39,7 @@ enum { /* no MMU emulation */ int no_mmu_map_address(CPUMIPSState *env, hwaddr *physical, int *prot, - target_ulong address, int rw) + target_ulong address, MMUAccessType access_type) { *physical = address; *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC; @@ -48,7 +48,7 @@ int no_mmu_map_address(CPUMIPSState *env, hwaddr *physical, int *prot, /* fixed mapping MMU emulation */ int fixed_mmu_map_address(CPUMIPSState *env, hwaddr *physical, int *prot, - target_ulong address, int rw) + target_ulong address, MMUAccessType access_type) { if (address <= (int32_t)0x7FFFFFFFUL) { if (!(env->CP0_Status & (1 << CP0St_ERL))) { @@ -68,7 +68,7 @@ int fixed_mmu_map_address(CPUMIPSState *env, hwaddr *physical, int *prot, /* MIPS32/MIPS64 R4000-style MMU emulation */ int r4k_map_address(CPUMIPSState *env, hwaddr *physical, int *prot, - target_ulong address, int rw) + target_ulong address, MMUAccessType access_type) { uint16_t ASID = env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask; uint32_t MMID = env->CP0_MemoryMapID; @@ -97,13 +97,13 @@ int r4k_map_address(CPUMIPSState *env, hwaddr *physical, int *prot, if (!(n ? tlb->V1 : tlb->V0)) { return TLBRET_INVALID; } - if (rw == MMU_INST_FETCH && (n ? tlb->XI1 : tlb->XI0)) { + if (access_type == MMU_INST_FETCH && (n ? tlb->XI1 : tlb->XI0)) { return TLBRET_XI; } - if (rw == MMU_DATA_LOAD && (n ? tlb->RI1 : tlb->RI0)) { + if (access_type == MMU_DATA_LOAD && (n ? tlb->RI1 : tlb->RI0)) { return TLBRET_RI; } - if (rw != MMU_DATA_STORE || (n ? tlb->D1 : tlb->D0)) { + if (access_type != MMU_DATA_STORE || (n ? tlb->D1 : tlb->D0)) { *physical = tlb->PFN[n] | (address & (mask >> 1)); *prot = PAGE_READ; if (n ? tlb->D1 : tlb->D0) { -- cgit v1.2.3-55-g7522 From bca3763be27adbc12fa65aeab51e429fd75a58cd Mon Sep 17 00:00:00 2001 From: Philippe Mathieu-Daudé Date: Sat, 20 Feb 2021 21:19:54 +0100 Subject: target/mips: Remove unused 'rw' argument from page_table_walk_refill() As the 'rw' argument is unused, remove it. Reported-by: Richard Henderson Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Message-Id: <20210220202026.2305667-1-f4bug@amsat.org> --- target/mips/tlb_helper.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/target/mips/tlb_helper.c b/target/mips/tlb_helper.c index b48f892a51..8d3ea49780 100644 --- a/target/mips/tlb_helper.c +++ b/target/mips/tlb_helper.c @@ -622,8 +622,8 @@ static int walk_directory(CPUMIPSState *env, uint64_t *vaddr, } } -static bool page_table_walk_refill(CPUMIPSState *env, vaddr address, int rw, - int mmu_idx) +static bool page_table_walk_refill(CPUMIPSState *env, vaddr address, + int mmu_idx) { int gdw = (env->CP0_PWSize >> CP0PS_GDW) & 0x3F; int udw = (env->CP0_PWSize >> CP0PS_UDW) & 0x3F; @@ -879,7 +879,7 @@ bool mips_cpu_tlb_fill(CPUState *cs, vaddr address, int size, int mode = (env->hflags & MIPS_HFLAG_KSU); bool ret_walker; env->hflags &= ~MIPS_HFLAG_KSU; - ret_walker = page_table_walk_refill(env, address, access_type, mmu_idx); + ret_walker = page_table_walk_refill(env, address, mmu_idx); env->hflags |= mode; if (ret_walker) { ret = get_physical_address(env, &physical, &prot, address, -- cgit v1.2.3-55-g7522 From 1e3b675b3e946f5c2b4b1aa96dc6413af8db9f04 Mon Sep 17 00:00:00 2001 From: Philippe Mathieu-Daudé Date: Sun, 7 Feb 2021 21:30:55 +0100 Subject: target/mips: Include missing "tcg/tcg.h" header Commit 83be6b54123 ("Fix MSA instructions LD. on big endian host") introduced use of typedef/prototypes declared in "tcg/tcg.h" without including it. This was not a problem because "tcg/tcg.h" is pulled in by "exec/cpu_ldst.h". To be able to remove this header there, we first need to include it here in op_helper.c, else we get: [222/337] Compiling C object libqemu-mips-softmmu.fa.p/target_mips_msa_helper.c.o target/mips/msa_helper.c: In function ‘helper_msa_ld_b’: target/mips/msa_helper.c:8214:9: error: unknown type name ‘TCGMemOpIdx’ 8214 | TCGMemOpIdx oi = make_memop_idx(MO_TE | DF | MO_UNALN, \ | ^~~~~~~~~~~ target/mips/msa_helper.c:8224:5: note: in expansion of macro ‘MEMOP_IDX’ 8224 | MEMOP_IDX(DF_BYTE) | ^~~~~~~~~ target/mips/msa_helper.c:8214:26: error: implicit declaration of function ‘make_memop_idx’ [-Werror=implicit-function-declaration] 8214 | TCGMemOpIdx oi = make_memop_idx(MO_TE | DF | MO_UNALN, \ | ^~~~~~~~~~~~~~ target/mips/msa_helper.c:8227:18: error: implicit declaration of function ‘helper_ret_ldub_mmu’ [-Werror=implicit-function-declaration] 8227 | pwd->b[0] = helper_ret_ldub_mmu(env, addr + (0 << DF_BYTE), oi, GETPC()); | ^~~~~~~~~~~~~~~~~~~ cc1: all warnings being treated as errors Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20210207232310.2505283-4-f4bug@amsat.org> --- target/mips/msa_helper.c | 1 + 1 file changed, 1 insertion(+) diff --git a/target/mips/msa_helper.c b/target/mips/msa_helper.c index 1298a1917c..4caefe29ad 100644 --- a/target/mips/msa_helper.c +++ b/target/mips/msa_helper.c @@ -20,6 +20,7 @@ #include "qemu/osdep.h" #include "cpu.h" #include "internal.h" +#include "tcg/tcg.h" #include "exec/exec-all.h" #include "exec/helper-proto.h" #include "exec/memop.h" -- cgit v1.2.3-55-g7522 From 9f5f7691dee18b0a0d6e0d8e291b7c12da85de17 Mon Sep 17 00:00:00 2001 From: Philippe Mathieu-Daudé Date: Sun, 14 Feb 2021 18:58:33 +0100 Subject: target/mips: Make cpu_HI/LO registers public We will access the cpu_HI/LO registers outside of translate.c. Make them publicly accessible. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Message-Id: <20210214175912.732946-4-f4bug@amsat.org> Signed-off-by: Philippe Mathieu-Daudé --- target/mips/translate.c | 2 +- target/mips/translate.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/target/mips/translate.c b/target/mips/translate.c index a6e835809a..c20f630b7e 100644 --- a/target/mips/translate.c +++ b/target/mips/translate.c @@ -2179,7 +2179,7 @@ enum { /* global register indices */ TCGv cpu_gpr[32], cpu_PC; -static TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC]; +TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC]; static TCGv cpu_dspctrl, btarget; TCGv bcond; static TCGv cpu_lladdr, cpu_llval; diff --git a/target/mips/translate.h b/target/mips/translate.h index f47b5f2c8d..2a1d8f570b 100644 --- a/target/mips/translate.h +++ b/target/mips/translate.h @@ -145,6 +145,7 @@ bool gen_lsa(DisasContext *ctx, int rd, int rt, int rs, int sa); bool gen_dlsa(DisasContext *ctx, int rd, int rt, int rs, int sa); extern TCGv cpu_gpr[32], cpu_PC; +extern TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC]; extern TCGv_i32 fpu_fcr0, fpu_fcr31; extern TCGv_i64 fpu_f64[32]; extern TCGv bcond; -- cgit v1.2.3-55-g7522 From cefd68f6b1e20639ba95d4eb8b4a99b5e00d93d3 Mon Sep 17 00:00:00 2001 From: Philippe Mathieu-Daudé Date: Sun, 14 Feb 2021 18:58:34 +0100 Subject: target/mips: Promote 128-bit multimedia registers as global ones The cpu::mmr[] array contains the upper halves of 128-bit GPR registers. While they are only used by the R5900 CPU, the concept is generic and could be used by another MIPS implementation. Rename 'cpu::mmr' as 'cpu::gpr_hi' and make them global. When the code is similar to the GPR lower halves, move it close by. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Message-Id: <20210214175912.732946-5-f4bug@amsat.org> Signed-off-by: Philippe Mathieu-Daudé --- target/mips/cpu.h | 10 +++++++--- target/mips/translate.c | 48 ++++++++++++++++++++++++------------------------ target/mips/translate.h | 3 +++ 3 files changed, 34 insertions(+), 27 deletions(-) diff --git a/target/mips/cpu.h b/target/mips/cpu.h index 9e6028f8e6..075c24abda 100644 --- a/target/mips/cpu.h +++ b/target/mips/cpu.h @@ -460,6 +460,13 @@ typedef struct mips_def_t mips_def_t; typedef struct TCState TCState; struct TCState { target_ulong gpr[32]; +#if defined(TARGET_MIPS64) + /* + * For CPUs using 128-bit GPR registers, we put the lower halves in gpr[]) + * and the upper halves in gpr_hi[]. + */ + uint64_t gpr_hi[32]; +#endif /* TARGET_MIPS64 */ target_ulong PC; target_ulong HI[MIPS_DSP_ACC]; target_ulong LO[MIPS_DSP_ACC]; @@ -505,9 +512,6 @@ struct TCState { float_status msa_fp_status; - /* Upper 64-bit MMRs (multimedia registers); the lower 64-bit are GPRs */ - uint64_t mmr[32]; - #define NUMBER_OF_MXU_REGISTERS 16 target_ulong mxu_gpr[NUMBER_OF_MXU_REGISTERS - 1]; target_ulong mxu_cr; diff --git a/target/mips/translate.c b/target/mips/translate.c index c20f630b7e..2df7659247 100644 --- a/target/mips/translate.c +++ b/target/mips/translate.c @@ -2179,6 +2179,11 @@ enum { /* global register indices */ TCGv cpu_gpr[32], cpu_PC; +/* + * For CPUs using 128-bit GPR registers, we put the lower halves in cpu_gpr[]) + * and the upper halves in cpu_gpr_hi[]. + */ +TCGv_i64 cpu_gpr_hi[32]; TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC]; static TCGv cpu_dspctrl, btarget; TCGv bcond; @@ -2187,11 +2192,6 @@ static TCGv_i32 hflags; TCGv_i32 fpu_fcr0, fpu_fcr31; TCGv_i64 fpu_f64[32]; -#if defined(TARGET_MIPS64) -/* Upper halves of R5900's 128-bit registers: MMRs (multimedia registers) */ -static TCGv_i64 cpu_mmr[32]; -#endif - #if !defined(TARGET_MIPS64) /* MXU registers */ static TCGv mxu_gpr[NUMBER_OF_MXU_REGISTERS - 1]; @@ -24784,7 +24784,7 @@ static void gen_mmi_pcpyh(DisasContext *ctx) /* nop */ } else if (rt == 0) { tcg_gen_movi_i64(cpu_gpr[rd], 0); - tcg_gen_movi_i64(cpu_mmr[rd], 0); + tcg_gen_movi_i64(cpu_gpr_hi[rd], 0); } else { TCGv_i64 t0 = tcg_temp_new(); TCGv_i64 t1 = tcg_temp_new(); @@ -24802,7 +24802,7 @@ static void gen_mmi_pcpyh(DisasContext *ctx) tcg_gen_mov_i64(cpu_gpr[rd], t1); - tcg_gen_andi_i64(t0, cpu_mmr[rt], mask); + tcg_gen_andi_i64(t0, cpu_gpr_hi[rt], mask); tcg_gen_movi_i64(t1, 0); tcg_gen_or_i64(t1, t0, t1); tcg_gen_shli_i64(t0, t0, 16); @@ -24812,7 +24812,7 @@ static void gen_mmi_pcpyh(DisasContext *ctx) tcg_gen_shli_i64(t0, t0, 16); tcg_gen_or_i64(t1, t0, t1); - tcg_gen_mov_i64(cpu_mmr[rd], t1); + tcg_gen_mov_i64(cpu_gpr_hi[rd], t1); tcg_temp_free(t0); tcg_temp_free(t1); @@ -24844,9 +24844,9 @@ static void gen_mmi_pcpyld(DisasContext *ctx) /* nop */ } else { if (rs == 0) { - tcg_gen_movi_i64(cpu_mmr[rd], 0); + tcg_gen_movi_i64(cpu_gpr_hi[rd], 0); } else { - tcg_gen_mov_i64(cpu_mmr[rd], cpu_gpr[rs]); + tcg_gen_mov_i64(cpu_gpr_hi[rd], cpu_gpr[rs]); } if (rt == 0) { tcg_gen_movi_i64(cpu_gpr[rd], 0); @@ -24885,13 +24885,13 @@ static void gen_mmi_pcpyud(DisasContext *ctx) if (rs == 0) { tcg_gen_movi_i64(cpu_gpr[rd], 0); } else { - tcg_gen_mov_i64(cpu_gpr[rd], cpu_mmr[rs]); + tcg_gen_mov_i64(cpu_gpr[rd], cpu_gpr_hi[rs]); } if (rt == 0) { - tcg_gen_movi_i64(cpu_mmr[rd], 0); + tcg_gen_movi_i64(cpu_gpr_hi[rd], 0); } else { if (rd != rt) { - tcg_gen_mov_i64(cpu_mmr[rd], cpu_mmr[rt]); + tcg_gen_mov_i64(cpu_gpr_hi[rd], cpu_gpr_hi[rt]); } } } @@ -29285,6 +29285,16 @@ void mips_tcg_init(void) offsetof(CPUMIPSState, active_tc.gpr[i]), regnames[i]); +#if defined(TARGET_MIPS64) + cpu_gpr_hi[0] = NULL; + + for (unsigned i = 1; i < 32; i++) { + cpu_gpr_hi[i] = tcg_global_mem_new_i64(cpu_env, + offsetof(CPUMIPSState, + active_tc.gpr_hi[i]), + regnames[i]); + } +#endif /* !TARGET_MIPS64 */ for (i = 0; i < 32; i++) { int off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[0]); @@ -29323,16 +29333,6 @@ void mips_tcg_init(void) cpu_llval = tcg_global_mem_new(cpu_env, offsetof(CPUMIPSState, llval), "llval"); -#if defined(TARGET_MIPS64) - cpu_mmr[0] = NULL; - for (i = 1; i < 32; i++) { - cpu_mmr[i] = tcg_global_mem_new_i64(cpu_env, - offsetof(CPUMIPSState, - active_tc.mmr[i]), - regnames[i]); - } -#endif - #if !defined(TARGET_MIPS64) for (i = 0; i < NUMBER_OF_MXU_REGISTERS - 1; i++) { mxu_gpr[i] = tcg_global_mem_new(cpu_env, @@ -29344,7 +29344,7 @@ void mips_tcg_init(void) mxu_CR = tcg_global_mem_new(cpu_env, offsetof(CPUMIPSState, active_tc.mxu_cr), mxuregnames[NUMBER_OF_MXU_REGISTERS - 1]); -#endif +#endif /* !TARGET_MIPS64 */ } void restore_state_to_opc(CPUMIPSState *env, TranslationBlock *tb, diff --git a/target/mips/translate.h b/target/mips/translate.h index 2a1d8f570b..3014c20cad 100644 --- a/target/mips/translate.h +++ b/target/mips/translate.h @@ -145,6 +145,9 @@ bool gen_lsa(DisasContext *ctx, int rd, int rt, int rs, int sa); bool gen_dlsa(DisasContext *ctx, int rd, int rt, int rs, int sa); extern TCGv cpu_gpr[32], cpu_PC; +#if defined(TARGET_MIPS64) +extern TCGv_i64 cpu_gpr_hi[32]; +#endif extern TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC]; extern TCGv_i32 fpu_fcr0, fpu_fcr31; extern TCGv_i64 fpu_f64[32]; -- cgit v1.2.3-55-g7522 From b5b63d43a0d2b3c3a914a30b0443ce3f04c0db5c Mon Sep 17 00:00:00 2001 From: Philippe Mathieu-Daudé Date: Sun, 14 Feb 2021 18:58:35 +0100 Subject: target/mips: Rename 128-bit upper halve GPR registers TCG displays the upper halve registers with the same name as their lower halves. Rename the upper halves with the '[hi]' suffix. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Message-Id: <20210214175912.732946-6-f4bug@amsat.org> Signed-off-by: Philippe Mathieu-Daudé --- target/mips/translate.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/target/mips/translate.c b/target/mips/translate.c index 2df7659247..5228e04084 100644 --- a/target/mips/translate.c +++ b/target/mips/translate.c @@ -29289,10 +29289,12 @@ void mips_tcg_init(void) cpu_gpr_hi[0] = NULL; for (unsigned i = 1; i < 32; i++) { + g_autofree char *rname = g_strdup_printf("%s[hi]", regnames[i]); + cpu_gpr_hi[i] = tcg_global_mem_new_i64(cpu_env, offsetof(CPUMIPSState, active_tc.gpr_hi[i]), - regnames[i]); + rname); } #endif /* !TARGET_MIPS64 */ for (i = 0; i < 32; i++) { -- cgit v1.2.3-55-g7522 From 61f4e0ec0dcedd2ade310aeb536ae750a0f7eef4 Mon Sep 17 00:00:00 2001 From: Philippe Mathieu-Daudé Date: Sun, 14 Feb 2021 18:58:36 +0100 Subject: target/mips: Introduce gen_load_gpr_hi() / gen_store_gpr_hi() helpers Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Message-Id: <20210214175912.732946-7-f4bug@amsat.org> Signed-off-by: Philippe Mathieu-Daudé --- target/mips/translate.c | 18 ++++++++++++++++++ target/mips/translate.h | 4 ++++ 2 files changed, 22 insertions(+) diff --git a/target/mips/translate.c b/target/mips/translate.c index 5228e04084..a303c36be3 100644 --- a/target/mips/translate.c +++ b/target/mips/translate.c @@ -2291,6 +2291,24 @@ void gen_store_gpr(TCGv t, int reg) } } +#if defined(TARGET_MIPS64) +void gen_load_gpr_hi(TCGv_i64 t, int reg) +{ + if (reg == 0) { + tcg_gen_movi_i64(t, 0); + } else { + tcg_gen_mov_i64(t, cpu_gpr_hi[reg]); + } +} + +void gen_store_gpr_hi(TCGv_i64 t, int reg) +{ + if (reg != 0) { + tcg_gen_mov_i64(cpu_gpr_hi[reg], t); + } +} +#endif /* TARGET_MIPS64 */ + /* Moves to/from shadow registers. */ static inline void gen_load_srsgpr(int from, int to) { diff --git a/target/mips/translate.h b/target/mips/translate.h index 3014c20cad..468e29d757 100644 --- a/target/mips/translate.h +++ b/target/mips/translate.h @@ -131,6 +131,10 @@ void gen_move_low32(TCGv ret, TCGv_i64 arg); void gen_move_high32(TCGv ret, TCGv_i64 arg); void gen_load_gpr(TCGv t, int reg); void gen_store_gpr(TCGv t, int reg); +#if defined(TARGET_MIPS64) +void gen_load_gpr_hi(TCGv_i64 t, int reg); +void gen_store_gpr_hi(TCGv_i64 t, int reg); +#endif /* TARGET_MIPS64 */ void gen_load_fpr32(DisasContext *ctx, TCGv_i32 t, int reg); void gen_load_fpr64(DisasContext *ctx, TCGv_i64 t, int reg); void gen_store_fpr32(DisasContext *ctx, TCGv_i32 t, int reg); -- cgit v1.2.3-55-g7522 From 3bc313c4f51a213ebcb172286b575f8d591c634f Mon Sep 17 00:00:00 2001 From: Philippe Mathieu-Daudé Date: Sun, 14 Feb 2021 18:58:37 +0100 Subject: target/mips: Use GPR move functions in gen_HILO1_tx79() We have handy functions to access GPR. Use gen_store_gpr() for Move From HI/LO Register and gen_load_gpr() for Move To opcodes. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Message-Id: <20210214175912.732946-8-f4bug@amsat.org> Signed-off-by: Philippe Mathieu-Daudé --- target/mips/translate.c | 21 ++++----------------- 1 file changed, 4 insertions(+), 17 deletions(-) diff --git a/target/mips/translate.c b/target/mips/translate.c index a303c36be3..70891c37cd 100644 --- a/target/mips/translate.c +++ b/target/mips/translate.c @@ -4126,31 +4126,18 @@ static void gen_shift(DisasContext *ctx, uint32_t opc, /* Copy GPR to and from TX79 HI1/LO1 register. */ static void gen_HILO1_tx79(DisasContext *ctx, uint32_t opc, int reg) { - if (reg == 0 && (opc == MMI_OPC_MFHI1 || opc == MMI_OPC_MFLO1)) { - /* Treat as NOP. */ - return; - } - switch (opc) { case MMI_OPC_MFHI1: - tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[1]); + gen_store_gpr(cpu_HI[1], reg); break; case MMI_OPC_MFLO1: - tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[1]); + gen_store_gpr(cpu_LO[1], reg); break; case MMI_OPC_MTHI1: - if (reg != 0) { - tcg_gen_mov_tl(cpu_HI[1], cpu_gpr[reg]); - } else { - tcg_gen_movi_tl(cpu_HI[1], 0); - } + gen_load_gpr(cpu_HI[1], reg); break; case MMI_OPC_MTLO1: - if (reg != 0) { - tcg_gen_mov_tl(cpu_LO[1], cpu_gpr[reg]); - } else { - tcg_gen_movi_tl(cpu_LO[1], 0); - } + gen_load_gpr(cpu_LO[1], reg); break; default: MIPS_INVAL("mfthilo1 TX79"); -- cgit v1.2.3-55-g7522 From 6be6e4bc7697ec902c536140b3d28938f2f68ba6 Mon Sep 17 00:00:00 2001 From: BALATON Zoltan Date: Sat, 9 Jan 2021 21:16:36 +0100 Subject: vt82c686: Move superio memory region to SuperIOConfig struct The superio memory region holds the io space index/data registers used to access the superio config registers that are implemented in struct SuperIOConfig. To keep these related things together move the memory region to SuperIOConfig and rename it accordingly. Also remove the unused "data" member of SuperIOConfig which is not needed as we store actual data values in the regs array. Signed-off-by: BALATON Zoltan Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Jiaxun Yang Message-Id: Signed-off-by: Philippe Mathieu-Daudé --- hw/isa/vt82c686.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/hw/isa/vt82c686.c b/hw/isa/vt82c686.c index a6f5a0843d..30fe02f4c6 100644 --- a/hw/isa/vt82c686.c +++ b/hw/isa/vt82c686.c @@ -29,12 +29,11 @@ typedef struct SuperIOConfig { uint8_t regs[0x100]; uint8_t index; - uint8_t data; + MemoryRegion io; } SuperIOConfig; struct VT82C686BISAState { PCIDevice dev; - MemoryRegion superio; SuperIOConfig superio_cfg; }; @@ -128,8 +127,9 @@ static void vt82c686b_write_config(PCIDevice *d, uint32_t addr, trace_via_isa_write(addr, val, len); pci_default_write_config(d, addr, val, len); - if (addr == 0x85) { /* enable or disable super IO configure */ - memory_region_set_enabled(&s->superio, val & 0x2); + if (addr == 0x85) { + /* BIT(1): enable or disable superio config io ports */ + memory_region_set_enabled(&s->superio_cfg.io, val & BIT(1)); } } @@ -311,15 +311,15 @@ static void vt82c686b_realize(PCIDevice *d, Error **errp) } } - memory_region_init_io(&s->superio, OBJECT(d), &superio_cfg_ops, - &s->superio_cfg, "superio", 2); - memory_region_set_enabled(&s->superio, false); + memory_region_init_io(&s->superio_cfg.io, OBJECT(d), &superio_cfg_ops, + &s->superio_cfg, "superio_cfg", 2); + memory_region_set_enabled(&s->superio_cfg.io, false); /* * The floppy also uses 0x3f0 and 0x3f1. * But we do not emulate a floppy, so just set it here. */ memory_region_add_subregion(isa_bus->address_space_io, 0x3f0, - &s->superio); + &s->superio_cfg.io); } static void via_class_init(ObjectClass *klass, void *data) -- cgit v1.2.3-55-g7522 From 94349bffda0ae13b4d7c9c042bd6c94fc6a5b9bf Mon Sep 17 00:00:00 2001 From: BALATON Zoltan Date: Sat, 9 Jan 2021 21:16:36 +0100 Subject: vt82c686: Reorganise code Move lines around so that object definitions become consecutive and not scattered around. This brings functions belonging to an object together so it's clearer what is defined and what parts belong to which object. Signed-off-by: BALATON Zoltan Reviewed-by: Philippe Mathieu-Daudé Message-Id: <9f942989dba46fc1c23b881f6cb135948f818c2f.1610223397.git.balaton@eik.bme.hu> Signed-off-by: Philippe Mathieu-Daudé --- hw/isa/vt82c686.c | 279 +++++++++++++++++++++++++++--------------------------- 1 file changed, 140 insertions(+), 139 deletions(-) diff --git a/hw/isa/vt82c686.c b/hw/isa/vt82c686.c index 30fe02f4c6..fe8961b057 100644 --- a/hw/isa/vt82c686.c +++ b/hw/isa/vt82c686.c @@ -26,112 +26,7 @@ #include "exec/address-spaces.h" #include "trace.h" -typedef struct SuperIOConfig { - uint8_t regs[0x100]; - uint8_t index; - MemoryRegion io; -} SuperIOConfig; - -struct VT82C686BISAState { - PCIDevice dev; - SuperIOConfig superio_cfg; -}; - -OBJECT_DECLARE_SIMPLE_TYPE(VT82C686BISAState, VT82C686B_ISA) - -static void superio_cfg_write(void *opaque, hwaddr addr, uint64_t data, - unsigned size) -{ - SuperIOConfig *sc = opaque; - - if (addr == 0x3f0) { /* config index register */ - sc->index = data & 0xff; - } else { - bool can_write = true; - /* 0x3f1, config data register */ - trace_via_superio_write(sc->index, data & 0xff); - switch (sc->index) { - case 0x00 ... 0xdf: - case 0xe4: - case 0xe5: - case 0xe9 ... 0xed: - case 0xf3: - case 0xf5: - case 0xf7: - case 0xf9 ... 0xfb: - case 0xfd ... 0xff: - can_write = false; - break; - /* case 0xe6 ... 0xe8: Should set base port of parallel and serial */ - default: - break; - - } - if (can_write) { - sc->regs[sc->index] = data & 0xff; - } - } -} - -static uint64_t superio_cfg_read(void *opaque, hwaddr addr, unsigned size) -{ - SuperIOConfig *sc = opaque; - uint8_t val = sc->regs[sc->index]; - - trace_via_superio_read(sc->index, val); - return val; -} - -static const MemoryRegionOps superio_cfg_ops = { - .read = superio_cfg_read, - .write = superio_cfg_write, - .endianness = DEVICE_NATIVE_ENDIAN, - .impl = { - .min_access_size = 1, - .max_access_size = 1, - }, -}; - -static void vt82c686b_isa_reset(DeviceState *dev) -{ - VT82C686BISAState *s = VT82C686B_ISA(dev); - uint8_t *pci_conf = s->dev.config; - - pci_set_long(pci_conf + PCI_CAPABILITY_LIST, 0x000000c0); - pci_set_word(pci_conf + PCI_COMMAND, PCI_COMMAND_IO | PCI_COMMAND_MEMORY | - PCI_COMMAND_MASTER | PCI_COMMAND_SPECIAL); - pci_set_word(pci_conf + PCI_STATUS, PCI_STATUS_DEVSEL_MEDIUM); - - pci_conf[0x48] = 0x01; /* Miscellaneous Control 3 */ - pci_conf[0x4a] = 0x04; /* IDE interrupt Routing */ - pci_conf[0x4f] = 0x03; /* DMA/Master Mem Access Control 3 */ - pci_conf[0x50] = 0x2d; /* PnP DMA Request Control */ - pci_conf[0x59] = 0x04; - pci_conf[0x5a] = 0x04; /* KBC/RTC Control*/ - pci_conf[0x5f] = 0x04; - pci_conf[0x77] = 0x10; /* GPIO Control 1/2/3/4 */ - - s->superio_cfg.regs[0xe0] = 0x3c; /* Device ID */ - s->superio_cfg.regs[0xe2] = 0x03; /* Function select */ - s->superio_cfg.regs[0xe3] = 0xfc; /* Floppy ctrl base addr */ - s->superio_cfg.regs[0xe6] = 0xde; /* Parallel port base addr */ - s->superio_cfg.regs[0xe7] = 0xfe; /* Serial port 1 base addr */ - s->superio_cfg.regs[0xe8] = 0xbe; /* Serial port 2 base addr */ -} - -/* write config pci function0 registers. PCI-ISA bridge */ -static void vt82c686b_write_config(PCIDevice *d, uint32_t addr, - uint32_t val, int len) -{ - VT82C686BISAState *s = VT82C686B_ISA(d); - - trace_via_isa_write(addr, val, len); - pci_default_write_config(d, addr, val, len); - if (addr == 0x85) { - /* BIT(1): enable or disable superio config io ports */ - memory_region_set_enabled(&s->superio_cfg.io, val & BIT(1)); - } -} +OBJECT_DECLARE_SIMPLE_TYPE(VT686PMState, VT82C686B_PM) struct VT686PMState { PCIDevice dev; @@ -142,30 +37,6 @@ struct VT686PMState { uint32_t smb_io_base; }; -OBJECT_DECLARE_SIMPLE_TYPE(VT686PMState, VT82C686B_PM) - -static void pm_update_sci(VT686PMState *s) -{ - int sci_level, pmsts; - - pmsts = acpi_pm1_evt_get_sts(&s->ar); - sci_level = (((pmsts & s->ar.pm1.evt.en) & - (ACPI_BITMASK_RT_CLOCK_ENABLE | - ACPI_BITMASK_POWER_BUTTON_ENABLE | - ACPI_BITMASK_GLOBAL_LOCK_ENABLE | - ACPI_BITMASK_TIMER_ENABLE)) != 0); - pci_set_irq(&s->dev, sci_level); - /* schedule a timer interruption if needed */ - acpi_pm_tmr_update(&s->ar, (s->ar.pm1.evt.en & ACPI_BITMASK_TIMER_ENABLE) && - !(pmsts & ACPI_BITMASK_TIMER_STATUS)); -} - -static void pm_tmr_timer(ACPIREGS *ar) -{ - VT686PMState *s = container_of(ar, VT686PMState, ar); - pm_update_sci(s); -} - static void pm_io_space_update(VT686PMState *s) { uint32_t pm_io_base; @@ -179,12 +50,6 @@ static void pm_io_space_update(VT686PMState *s) memory_region_transaction_commit(); } -static void pm_write_config(PCIDevice *d, uint32_t addr, uint32_t val, int len) -{ - trace_via_pm_write(addr, val, len); - pci_default_write_config(d, addr, val, len); -} - static int vmstate_acpi_post_load(void *opaque, int version_id) { VT686PMState *s = opaque; @@ -210,7 +75,34 @@ static const VMStateDescription vmstate_acpi = { } }; -/* vt82c686 pm init */ +static void pm_write_config(PCIDevice *d, uint32_t addr, uint32_t val, int len) +{ + trace_via_pm_write(addr, val, len); + pci_default_write_config(d, addr, val, len); +} + +static void pm_update_sci(VT686PMState *s) +{ + int sci_level, pmsts; + + pmsts = acpi_pm1_evt_get_sts(&s->ar); + sci_level = (((pmsts & s->ar.pm1.evt.en) & + (ACPI_BITMASK_RT_CLOCK_ENABLE | + ACPI_BITMASK_POWER_BUTTON_ENABLE | + ACPI_BITMASK_GLOBAL_LOCK_ENABLE | + ACPI_BITMASK_TIMER_ENABLE)) != 0); + pci_set_irq(&s->dev, sci_level); + /* schedule a timer interruption if needed */ + acpi_pm_tmr_update(&s->ar, (s->ar.pm1.evt.en & ACPI_BITMASK_TIMER_ENABLE) && + !(pmsts & ACPI_BITMASK_TIMER_STATUS)); +} + +static void pm_tmr_timer(ACPIREGS *ar) +{ + VT686PMState *s = container_of(ar, VT686PMState, ar); + pm_update_sci(s); +} + static void vt82c686b_pm_realize(PCIDevice *dev, Error **errp) { VT686PMState *s = VT82C686B_PM(dev); @@ -276,6 +168,87 @@ static const TypeInfo via_pm_info = { }, }; + +typedef struct SuperIOConfig { + uint8_t regs[0x100]; + uint8_t index; + MemoryRegion io; +} SuperIOConfig; + +static void superio_cfg_write(void *opaque, hwaddr addr, uint64_t data, + unsigned size) +{ + SuperIOConfig *sc = opaque; + + if (addr == 0x3f0) { /* config index register */ + sc->index = data & 0xff; + } else { + bool can_write = true; + /* 0x3f1, config data register */ + trace_via_superio_write(sc->index, data & 0xff); + switch (sc->index) { + case 0x00 ... 0xdf: + case 0xe4: + case 0xe5: + case 0xe9 ... 0xed: + case 0xf3: + case 0xf5: + case 0xf7: + case 0xf9 ... 0xfb: + case 0xfd ... 0xff: + can_write = false; + break; + /* case 0xe6 ... 0xe8: Should set base port of parallel and serial */ + default: + break; + + } + if (can_write) { + sc->regs[sc->index] = data & 0xff; + } + } +} + +static uint64_t superio_cfg_read(void *opaque, hwaddr addr, unsigned size) +{ + SuperIOConfig *sc = opaque; + uint8_t val = sc->regs[sc->index]; + + trace_via_superio_read(sc->index, val); + return val; +} + +static const MemoryRegionOps superio_cfg_ops = { + .read = superio_cfg_read, + .write = superio_cfg_write, + .endianness = DEVICE_NATIVE_ENDIAN, + .impl = { + .min_access_size = 1, + .max_access_size = 1, + }, +}; + + +OBJECT_DECLARE_SIMPLE_TYPE(VT82C686BISAState, VT82C686B_ISA) + +struct VT82C686BISAState { + PCIDevice dev; + SuperIOConfig superio_cfg; +}; + +static void vt82c686b_write_config(PCIDevice *d, uint32_t addr, + uint32_t val, int len) +{ + VT82C686BISAState *s = VT82C686B_ISA(d); + + trace_via_isa_write(addr, val, len); + pci_default_write_config(d, addr, val, len); + if (addr == 0x85) { + /* BIT(1): enable or disable superio config io ports */ + memory_region_set_enabled(&s->superio_cfg.io, val & BIT(1)); + } +} + static const VMStateDescription vmstate_via = { .name = "vt82c686b", .version_id = 1, @@ -286,7 +259,33 @@ static const VMStateDescription vmstate_via = { } }; -/* init the PCI-to-ISA bridge */ +static void vt82c686b_isa_reset(DeviceState *dev) +{ + VT82C686BISAState *s = VT82C686B_ISA(dev); + uint8_t *pci_conf = s->dev.config; + + pci_set_long(pci_conf + PCI_CAPABILITY_LIST, 0x000000c0); + pci_set_word(pci_conf + PCI_COMMAND, PCI_COMMAND_IO | PCI_COMMAND_MEMORY | + PCI_COMMAND_MASTER | PCI_COMMAND_SPECIAL); + pci_set_word(pci_conf + PCI_STATUS, PCI_STATUS_DEVSEL_MEDIUM); + + pci_conf[0x48] = 0x01; /* Miscellaneous Control 3 */ + pci_conf[0x4a] = 0x04; /* IDE interrupt Routing */ + pci_conf[0x4f] = 0x03; /* DMA/Master Mem Access Control 3 */ + pci_conf[0x50] = 0x2d; /* PnP DMA Request Control */ + pci_conf[0x59] = 0x04; + pci_conf[0x5a] = 0x04; /* KBC/RTC Control*/ + pci_conf[0x5f] = 0x04; + pci_conf[0x77] = 0x10; /* GPIO Control 1/2/3/4 */ + + s->superio_cfg.regs[0xe0] = 0x3c; /* Device ID */ + s->superio_cfg.regs[0xe2] = 0x03; /* Function select */ + s->superio_cfg.regs[0xe3] = 0xfc; /* Floppy ctrl base addr */ + s->superio_cfg.regs[0xe6] = 0xde; /* Parallel port base addr */ + s->superio_cfg.regs[0xe7] = 0xfe; /* Serial port 1 base addr */ + s->superio_cfg.regs[0xe8] = 0xbe; /* Serial port 2 base addr */ +} + static void vt82c686b_realize(PCIDevice *d, Error **errp) { VT82C686BISAState *s = VT82C686B_ISA(d); @@ -354,6 +353,7 @@ static const TypeInfo via_info = { }, }; + static void vt82c686b_superio_class_init(ObjectClass *klass, void *data) { ISASuperIOClass *sc = ISA_SUPERIO_CLASS(klass); @@ -372,11 +372,12 @@ static const TypeInfo via_superio_info = { .class_init = vt82c686b_superio_class_init, }; + static void vt82c686b_register_types(void) { type_register_static(&via_pm_info); - type_register_static(&via_superio_info); type_register_static(&via_info); + type_register_static(&via_superio_info); } type_init(vt82c686b_register_types) -- cgit v1.2.3-55-g7522 From 911629e6d3773a8adeab48b488fadece0d7996b1 Mon Sep 17 00:00:00 2001 From: BALATON Zoltan Date: Sat, 9 Jan 2021 21:16:36 +0100 Subject: vt82c686: Fix SMBus IO base and configuration registers The base address of the SMBus io ports and its enabled status is set by registers in the PCI config space but this was not correctly emulated. Instead the SMBus registers were mapped on realize to the base address set by a property to the address expected by fuloong2e firmware. Fix the base and config register handling to more closely model hardware which allows to remove the property and allows the guest to control this mapping. Do all this in reset instead of realize so it's correctly updated on reset. Signed-off-by: BALATON Zoltan Reviewed-by: Jiaxun Yang Message-Id: Signed-off-by: Philippe Mathieu-Daudé --- hw/isa/vt82c686.c | 49 ++++++++++++++++++++++++++++++++++++------------- hw/mips/fuloong2e.c | 4 +--- 2 files changed, 37 insertions(+), 16 deletions(-) diff --git a/hw/isa/vt82c686.c b/hw/isa/vt82c686.c index fe8961b057..9c4d153022 100644 --- a/hw/isa/vt82c686.c +++ b/hw/isa/vt82c686.c @@ -22,6 +22,7 @@ #include "hw/i2c/pm_smbus.h" #include "qapi/error.h" #include "qemu/module.h" +#include "qemu/range.h" #include "qemu/timer.h" #include "exec/address-spaces.h" #include "trace.h" @@ -34,7 +35,6 @@ struct VT686PMState { ACPIREGS ar; APMState apm; PMSMBus smb; - uint32_t smb_io_base; }; static void pm_io_space_update(VT686PMState *s) @@ -50,11 +50,22 @@ static void pm_io_space_update(VT686PMState *s) memory_region_transaction_commit(); } +static void smb_io_space_update(VT686PMState *s) +{ + uint32_t smbase = pci_get_long(s->dev.config + 0x90) & 0xfff0UL; + + memory_region_transaction_begin(); + memory_region_set_address(&s->smb.io, smbase); + memory_region_set_enabled(&s->smb.io, s->dev.config[0xd2] & BIT(0)); + memory_region_transaction_commit(); +} + static int vmstate_acpi_post_load(void *opaque, int version_id) { VT686PMState *s = opaque; pm_io_space_update(s); + smb_io_space_update(s); return 0; } @@ -77,8 +88,18 @@ static const VMStateDescription vmstate_acpi = { static void pm_write_config(PCIDevice *d, uint32_t addr, uint32_t val, int len) { + VT686PMState *s = VT82C686B_PM(d); + trace_via_pm_write(addr, val, len); pci_default_write_config(d, addr, val, len); + if (ranges_overlap(addr, len, 0x90, 4)) { + uint32_t v = pci_get_long(s->dev.config + 0x90); + pci_set_long(s->dev.config + 0x90, (v & 0xfff0UL) | 1); + } + if (range_covers_byte(addr, len, 0xd2)) { + s->dev.config[0xd2] &= 0xf; + smb_io_space_update(s); + } } static void pm_update_sci(VT686PMState *s) @@ -103,6 +124,17 @@ static void pm_tmr_timer(ACPIREGS *ar) pm_update_sci(s); } +static void vt82c686b_pm_reset(DeviceState *d) +{ + VT686PMState *s = VT82C686B_PM(d); + + /* SMBus IO base */ + pci_set_long(s->dev.config + 0x90, 1); + s->dev.config[0xd2] = 0; + + smb_io_space_update(s); +} + static void vt82c686b_pm_realize(PCIDevice *dev, Error **errp) { VT686PMState *s = VT82C686B_PM(dev); @@ -116,13 +148,9 @@ static void vt82c686b_pm_realize(PCIDevice *dev, Error **errp) /* 0x48-0x4B is Power Management I/O Base */ pci_set_long(pci_conf + 0x48, 0x00000001); - /* SMB ports:0xeee0~0xeeef */ - s->smb_io_base = ((s->smb_io_base & 0xfff0) + 0x0); - pci_conf[0x90] = s->smb_io_base | 1; - pci_conf[0x91] = s->smb_io_base >> 8; - pci_conf[0xd2] = 0x90; pm_smbus_init(DEVICE(s), &s->smb, false); - memory_region_add_subregion(get_system_io(), s->smb_io_base, &s->smb.io); + memory_region_add_subregion(pci_address_space_io(dev), 0, &s->smb.io); + memory_region_set_enabled(&s->smb.io, false); apm_init(dev, &s->apm, NULL, s); @@ -135,11 +163,6 @@ static void vt82c686b_pm_realize(PCIDevice *dev, Error **errp) acpi_pm1_cnt_init(&s->ar, &s->io, false, false, 2); } -static Property via_pm_properties[] = { - DEFINE_PROP_UINT32("smb_io_base", VT686PMState, smb_io_base, 0), - DEFINE_PROP_END_OF_LIST(), -}; - static void via_pm_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); @@ -151,10 +174,10 @@ static void via_pm_class_init(ObjectClass *klass, void *data) k->device_id = PCI_DEVICE_ID_VIA_ACPI; k->class_id = PCI_CLASS_BRIDGE_OTHER; k->revision = 0x40; + dc->reset = vt82c686b_pm_reset; dc->desc = "PM"; dc->vmsd = &vmstate_acpi; set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); - device_class_set_props(dc, via_pm_properties); } static const TypeInfo via_pm_info = { diff --git a/hw/mips/fuloong2e.c b/hw/mips/fuloong2e.c index 1f3680fda3..94f4718147 100644 --- a/hw/mips/fuloong2e.c +++ b/hw/mips/fuloong2e.c @@ -230,9 +230,7 @@ static void vt82c686b_southbridge_init(PCIBus *pci_bus, int slot, qemu_irq intc, pci_create_simple(pci_bus, PCI_DEVFN(slot, 2), "vt82c686b-usb-uhci"); pci_create_simple(pci_bus, PCI_DEVFN(slot, 3), "vt82c686b-usb-uhci"); - dev = pci_new(PCI_DEVFN(slot, 4), TYPE_VT82C686B_PM); - qdev_prop_set_uint32(DEVICE(dev), "smb_io_base", 0xeee1); - pci_realize_and_unref(dev, pci_bus, &error_fatal); + dev = pci_create_simple(pci_bus, PCI_DEVFN(slot, 4), TYPE_VT82C686B_PM); *i2c_bus = I2C_BUS(qdev_get_child_bus(DEVICE(dev), "i2c")); /* Audio support */ -- cgit v1.2.3-55-g7522 From 35e360ed67400f792fae88627268440a6326a511 Mon Sep 17 00:00:00 2001 From: BALATON Zoltan Date: Sat, 9 Jan 2021 21:16:36 +0100 Subject: vt82c686: Make vt82c686-pm an I/O tracing region Previously just an empty RAM region was mapped on realize, now we add an empty io range logging access instead. I think the pm timer should be hooked up here but not sure guests need it. PMON on fuloong2e sets a base address but does not seem to enable region; the pegasos2 firmware pokes some regs but continues anyway so don't know if anything would make use of these facilities. Therefore this is just a clean up of previous state for now and not intending to fully implement missing functionality which could be done later if some guests need it. Signed-off-by: BALATON Zoltan Reviewed-by: Philippe Mathieu-Daudé Message-Id: [PMD: Split original patch, this is part 1/4 (make 'vt82c686-pm' an I/O tracing region)] Signed-off-by: Philippe Mathieu-Daudé --- hw/isa/trace-events | 2 ++ hw/isa/vt82c686.c | 26 ++++++++++++++++++++++++-- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/hw/isa/trace-events b/hw/isa/trace-events index d267d3e652..641d69eedf 100644 --- a/hw/isa/trace-events +++ b/hw/isa/trace-events @@ -17,5 +17,7 @@ apm_io_write(uint8_t addr, uint8_t val) "write addr=0x%x val=0x%02x" # vt82c686.c via_isa_write(uint32_t addr, uint32_t val, int len) "addr 0x%x val 0x%x len 0x%x" via_pm_write(uint32_t addr, uint32_t val, int len) "addr 0x%x val 0x%x len 0x%x" +via_pm_io_read(uint32_t addr, uint32_t val, int len) "addr 0x%x val 0x%x len 0x%x" +via_pm_io_write(uint32_t addr, uint32_t val, int len) "addr 0x%x val 0x%x len 0x%x" via_superio_read(uint8_t addr, uint8_t val) "addr 0x%x val 0x%x" via_superio_write(uint8_t addr, uint32_t val) "addr 0x%x val 0x%x" diff --git a/hw/isa/vt82c686.c b/hw/isa/vt82c686.c index 9c4d153022..7e6a07fca4 100644 --- a/hw/isa/vt82c686.c +++ b/hw/isa/vt82c686.c @@ -102,6 +102,27 @@ static void pm_write_config(PCIDevice *d, uint32_t addr, uint32_t val, int len) } } +static void pm_io_write(void *op, hwaddr addr, uint64_t data, unsigned size) +{ + trace_via_pm_io_write(addr, data, size); +} + +static uint64_t pm_io_read(void *op, hwaddr addr, unsigned size) +{ + trace_via_pm_io_read(addr, 0, size); + return 0; +} + +static const MemoryRegionOps pm_io_ops = { + .read = pm_io_read, + .write = pm_io_write, + .endianness = DEVICE_NATIVE_ENDIAN, + .impl = { + .min_access_size = 1, + .max_access_size = 1, + }, +}; + static void pm_update_sci(VT686PMState *s) { int sci_level, pmsts; @@ -154,9 +175,10 @@ static void vt82c686b_pm_realize(PCIDevice *dev, Error **errp) apm_init(dev, &s->apm, NULL, s); - memory_region_init(&s->io, OBJECT(dev), "vt82c686-pm", 64); + memory_region_init_io(&s->io, OBJECT(dev), &pm_io_ops, s, + "vt82c686-pm", 64); + memory_region_add_subregion(pci_address_space_io(dev), 0, &s->io); memory_region_set_enabled(&s->io, false); - memory_region_add_subregion(get_system_io(), 0, &s->io); acpi_pm_tmr_init(&s->ar, pm_tmr_timer, &s->io); acpi_pm1_evt_init(&s->ar, pm_tmr_timer, &s->io); -- cgit v1.2.3-55-g7522 From 40a0bba1e3feff9c3aa05e56db07eec9e72393e5 Mon Sep 17 00:00:00 2001 From: BALATON Zoltan Date: Sat, 9 Jan 2021 21:16:36 +0100 Subject: vt82c686: Correct vt82c686-pm I/O size Section "Offset 4B-48 – Power Management I/O Base" describes: Port Address for the base of the 128-byte Power Management I/O Register block. Correct the vt82c686-pm I/O region size. Signed-off-by: BALATON Zoltan Message-Id: [PMD: Split original patch, this is part 2/4, reduced size to 128B] Signed-off-by: Philippe Mathieu-Daudé --- hw/isa/vt82c686.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/isa/vt82c686.c b/hw/isa/vt82c686.c index 7e6a07fca4..fe8ae24c42 100644 --- a/hw/isa/vt82c686.c +++ b/hw/isa/vt82c686.c @@ -176,7 +176,7 @@ static void vt82c686b_pm_realize(PCIDevice *dev, Error **errp) apm_init(dev, &s->apm, NULL, s); memory_region_init_io(&s->io, OBJECT(dev), &pm_io_ops, s, - "vt82c686-pm", 64); + "vt82c686-pm", 128); memory_region_add_subregion(pci_address_space_io(dev), 0, &s->io); memory_region_set_enabled(&s->io, false); -- cgit v1.2.3-55-g7522 From 9af8e529b91d6e8a0c2911281b39179f184f09bf Mon Sep 17 00:00:00 2001 From: BALATON Zoltan Date: Sat, 9 Jan 2021 21:16:36 +0100 Subject: vt82c686: Correctly reset all registers to default values on reset Reset the registers in the DeviceReset() handler which is called on each device reset, not in DeviceRealize() which is called once. Bit 0 of 'Power Mgmt I/O Base' register (offset 0x48) is always set. Signed-off-by: BALATON Zoltan Message-Id: Reviewed-by: Philippe Mathieu-Daudé [PMD: Split original patch, this is part 3/4 (move to reset), document] Signed-off-by: Philippe Mathieu-Daudé --- hw/isa/vt82c686.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/hw/isa/vt82c686.c b/hw/isa/vt82c686.c index fe8ae24c42..48ead5af55 100644 --- a/hw/isa/vt82c686.c +++ b/hw/isa/vt82c686.c @@ -149,9 +149,12 @@ static void vt82c686b_pm_reset(DeviceState *d) { VT686PMState *s = VT82C686B_PM(d); + memset(s->dev.config + PCI_CONFIG_HEADER_SIZE, 0, + PCI_CONFIG_SPACE_SIZE - PCI_CONFIG_HEADER_SIZE); + /* Power Management IO base */ + pci_set_long(s->dev.config + 0x48, 1); /* SMBus IO base */ pci_set_long(s->dev.config + 0x90, 1); - s->dev.config[0xd2] = 0; smb_io_space_update(s); } @@ -166,9 +169,6 @@ static void vt82c686b_pm_realize(PCIDevice *dev, Error **errp) pci_set_word(pci_conf + PCI_STATUS, PCI_STATUS_FAST_BACK | PCI_STATUS_DEVSEL_MEDIUM); - /* 0x48-0x4B is Power Management I/O Base */ - pci_set_long(pci_conf + 0x48, 0x00000001); - pm_smbus_init(DEVICE(s), &s->smb, false); memory_region_add_subregion(pci_address_space_io(dev), 0, &s->smb.io); memory_region_set_enabled(&s->smb.io, false); -- cgit v1.2.3-55-g7522 From 3ab1eea6bced10e314625cfa13fc9c9fa586486f Mon Sep 17 00:00:00 2001 From: BALATON Zoltan Date: Sat, 9 Jan 2021 21:16:36 +0100 Subject: vt82c686: Fix up power management io base and config Similar to the SMBus io registers there is a power management io range that is set via similar base address reg and enable bit. Some handling of this was already there but with several problems: using the wrong registers and bits, wrong size range, not acually updating mapping and handling reset correctly, nor emulating any of the actual io registers. Some of these errors are fixed up here. After this patch we use the correct base address register, enable bit and region size and allow guests to map/unmap this region, but we still don't emulate any of the registers in this range. PMD notes regarding the Configuration Space Power Management Registers: - 0x40 General Configuration 0 - 0x41 General Configuration 1 . Bit 7: I/O Enable for ACPI I/O Base - 0x48 Power Mgmt I/O Base . Bit 0: Always set . Bits 7-15: Power Management I/O Register Base Address (this explains the change 0xffc0 -> 0xff80) Signed-off-by: BALATON Zoltan Message-Id: [PMD: Split original patch, this is part 4/4, added notes] Signed-off-by: Philippe Mathieu-Daudé --- hw/isa/vt82c686.c | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/hw/isa/vt82c686.c b/hw/isa/vt82c686.c index 48ead5af55..cb2f714260 100644 --- a/hw/isa/vt82c686.c +++ b/hw/isa/vt82c686.c @@ -39,14 +39,11 @@ struct VT686PMState { static void pm_io_space_update(VT686PMState *s) { - uint32_t pm_io_base; - - pm_io_base = pci_get_long(s->dev.config + 0x40); - pm_io_base &= 0xffc0; + uint32_t pmbase = pci_get_long(s->dev.config + 0x48) & 0xff80UL; memory_region_transaction_begin(); - memory_region_set_enabled(&s->io, s->dev.config[0x80] & 1); - memory_region_set_address(&s->io, pm_io_base); + memory_region_set_address(&s->io, pmbase); + memory_region_set_enabled(&s->io, s->dev.config[0x41] & BIT(7)); memory_region_transaction_commit(); } @@ -92,6 +89,13 @@ static void pm_write_config(PCIDevice *d, uint32_t addr, uint32_t val, int len) trace_via_pm_write(addr, val, len); pci_default_write_config(d, addr, val, len); + if (ranges_overlap(addr, len, 0x48, 4)) { + uint32_t v = pci_get_long(s->dev.config + 0x48); + pci_set_long(s->dev.config + 0x48, (v & 0xff80UL) | 1); + } + if (range_covers_byte(addr, len, 0x41)) { + pm_io_space_update(s); + } if (ranges_overlap(addr, len, 0x90, 4)) { uint32_t v = pci_get_long(s->dev.config + 0x90); pci_set_long(s->dev.config + 0x90, (v & 0xfff0UL) | 1); @@ -156,17 +160,15 @@ static void vt82c686b_pm_reset(DeviceState *d) /* SMBus IO base */ pci_set_long(s->dev.config + 0x90, 1); + pm_io_space_update(s); smb_io_space_update(s); } static void vt82c686b_pm_realize(PCIDevice *dev, Error **errp) { VT686PMState *s = VT82C686B_PM(dev); - uint8_t *pci_conf; - pci_conf = s->dev.config; - pci_set_word(pci_conf + PCI_COMMAND, 0); - pci_set_word(pci_conf + PCI_STATUS, PCI_STATUS_FAST_BACK | + pci_set_word(dev->config + PCI_STATUS, PCI_STATUS_FAST_BACK | PCI_STATUS_DEVSEL_MEDIUM); pm_smbus_init(DEVICE(s), &s->smb, false); -- cgit v1.2.3-55-g7522 From 084bf4b41d40ead572e45c47c6e5fca5b3eb997c Mon Sep 17 00:00:00 2001 From: BALATON Zoltan Date: Sat, 9 Jan 2021 21:16:36 +0100 Subject: vt82c686: Set user_creatable=false for VT82C686B_PM This device is part of the multifunction VIA superio/south bridge chip so not useful in itself. Signed-off-by: BALATON Zoltan Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Jiaxun Yang Message-Id: Signed-off-by: Philippe Mathieu-Daudé --- hw/isa/vt82c686.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hw/isa/vt82c686.c b/hw/isa/vt82c686.c index cb2f714260..5e2bf6d16c 100644 --- a/hw/isa/vt82c686.c +++ b/hw/isa/vt82c686.c @@ -200,8 +200,9 @@ static void via_pm_class_init(ObjectClass *klass, void *data) k->revision = 0x40; dc->reset = vt82c686b_pm_reset; dc->desc = "PM"; + /* Reason: part of VIA south bridge, does not exist stand alone */ + dc->user_creatable = false; dc->vmsd = &vmstate_acpi; - set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); } static const TypeInfo via_pm_info = { -- cgit v1.2.3-55-g7522 From e1a69736e5985ac2d45977d4d6482ab9cca71db8 Mon Sep 17 00:00:00 2001 From: BALATON Zoltan Date: Sat, 9 Jan 2021 21:16:36 +0100 Subject: vt82c686: Make vt82c686b-pm an abstract base class and add vt8231-pm based on it The vt82c686b-pm model can be shared between VT82C686B and VT8231. The only difference between the two is the device id in what we emulate so make an abstract via-pm model by renaming appropriately and add types for vt82c686b-pm and vt8231-pm based on it. Signed-off-by: BALATON Zoltan Reviewed-by: Philippe Mathieu-Daudé Message-Id: <34969fc7be984fa070479bfb9f748993a0aef31b.1610223397.git.balaton@eik.bme.hu> Signed-off-by: Philippe Mathieu-Daudé --- hw/isa/vt82c686.c | 84 +++++++++++++++++++++++++++++++---------------- include/hw/isa/vt82c686.h | 1 + include/hw/pci/pci_ids.h | 3 +- 3 files changed, 59 insertions(+), 29 deletions(-) diff --git a/hw/isa/vt82c686.c b/hw/isa/vt82c686.c index 5e2bf6d16c..0e812c4924 100644 --- a/hw/isa/vt82c686.c +++ b/hw/isa/vt82c686.c @@ -27,9 +27,10 @@ #include "exec/address-spaces.h" #include "trace.h" -OBJECT_DECLARE_SIMPLE_TYPE(VT686PMState, VT82C686B_PM) +#define TYPE_VIA_PM "via-pm" +OBJECT_DECLARE_SIMPLE_TYPE(ViaPMState, VIA_PM) -struct VT686PMState { +struct ViaPMState { PCIDevice dev; MemoryRegion io; ACPIREGS ar; @@ -37,7 +38,7 @@ struct VT686PMState { PMSMBus smb; }; -static void pm_io_space_update(VT686PMState *s) +static void pm_io_space_update(ViaPMState *s) { uint32_t pmbase = pci_get_long(s->dev.config + 0x48) & 0xff80UL; @@ -47,7 +48,7 @@ static void pm_io_space_update(VT686PMState *s) memory_region_transaction_commit(); } -static void smb_io_space_update(VT686PMState *s) +static void smb_io_space_update(ViaPMState *s) { uint32_t smbase = pci_get_long(s->dev.config + 0x90) & 0xfff0UL; @@ -59,7 +60,7 @@ static void smb_io_space_update(VT686PMState *s) static int vmstate_acpi_post_load(void *opaque, int version_id) { - VT686PMState *s = opaque; + ViaPMState *s = opaque; pm_io_space_update(s); smb_io_space_update(s); @@ -72,20 +73,20 @@ static const VMStateDescription vmstate_acpi = { .minimum_version_id = 1, .post_load = vmstate_acpi_post_load, .fields = (VMStateField[]) { - VMSTATE_PCI_DEVICE(dev, VT686PMState), - VMSTATE_UINT16(ar.pm1.evt.sts, VT686PMState), - VMSTATE_UINT16(ar.pm1.evt.en, VT686PMState), - VMSTATE_UINT16(ar.pm1.cnt.cnt, VT686PMState), - VMSTATE_STRUCT(apm, VT686PMState, 0, vmstate_apm, APMState), - VMSTATE_TIMER_PTR(ar.tmr.timer, VT686PMState), - VMSTATE_INT64(ar.tmr.overflow_time, VT686PMState), + VMSTATE_PCI_DEVICE(dev, ViaPMState), + VMSTATE_UINT16(ar.pm1.evt.sts, ViaPMState), + VMSTATE_UINT16(ar.pm1.evt.en, ViaPMState), + VMSTATE_UINT16(ar.pm1.cnt.cnt, ViaPMState), + VMSTATE_STRUCT(apm, ViaPMState, 0, vmstate_apm, APMState), + VMSTATE_TIMER_PTR(ar.tmr.timer, ViaPMState), + VMSTATE_INT64(ar.tmr.overflow_time, ViaPMState), VMSTATE_END_OF_LIST() } }; static void pm_write_config(PCIDevice *d, uint32_t addr, uint32_t val, int len) { - VT686PMState *s = VT82C686B_PM(d); + ViaPMState *s = VIA_PM(d); trace_via_pm_write(addr, val, len); pci_default_write_config(d, addr, val, len); @@ -127,7 +128,7 @@ static const MemoryRegionOps pm_io_ops = { }, }; -static void pm_update_sci(VT686PMState *s) +static void pm_update_sci(ViaPMState *s) { int sci_level, pmsts; @@ -145,13 +146,13 @@ static void pm_update_sci(VT686PMState *s) static void pm_tmr_timer(ACPIREGS *ar) { - VT686PMState *s = container_of(ar, VT686PMState, ar); + ViaPMState *s = container_of(ar, ViaPMState, ar); pm_update_sci(s); } -static void vt82c686b_pm_reset(DeviceState *d) +static void via_pm_reset(DeviceState *d) { - VT686PMState *s = VT82C686B_PM(d); + ViaPMState *s = VIA_PM(d); memset(s->dev.config + PCI_CONFIG_HEADER_SIZE, 0, PCI_CONFIG_SPACE_SIZE - PCI_CONFIG_HEADER_SIZE); @@ -164,9 +165,9 @@ static void vt82c686b_pm_reset(DeviceState *d) smb_io_space_update(s); } -static void vt82c686b_pm_realize(PCIDevice *dev, Error **errp) +static void via_pm_realize(PCIDevice *dev, Error **errp) { - VT686PMState *s = VT82C686B_PM(dev); + ViaPMState *s = VIA_PM(dev); pci_set_word(dev->config + PCI_STATUS, PCI_STATUS_FAST_BACK | PCI_STATUS_DEVSEL_MEDIUM); @@ -177,8 +178,7 @@ static void vt82c686b_pm_realize(PCIDevice *dev, Error **errp) apm_init(dev, &s->apm, NULL, s); - memory_region_init_io(&s->io, OBJECT(dev), &pm_io_ops, s, - "vt82c686-pm", 128); + memory_region_init_io(&s->io, OBJECT(dev), &pm_io_ops, s, "via-pm", 128); memory_region_add_subregion(pci_address_space_io(dev), 0, &s->io); memory_region_set_enabled(&s->io, false); @@ -187,35 +187,61 @@ static void vt82c686b_pm_realize(PCIDevice *dev, Error **errp) acpi_pm1_cnt_init(&s->ar, &s->io, false, false, 2); } +typedef struct via_pm_init_info { + uint16_t device_id; +} ViaPMInitInfo; + static void via_pm_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); + ViaPMInitInfo *info = data; - k->realize = vt82c686b_pm_realize; + k->realize = via_pm_realize; k->config_write = pm_write_config; k->vendor_id = PCI_VENDOR_ID_VIA; - k->device_id = PCI_DEVICE_ID_VIA_ACPI; + k->device_id = info->device_id; k->class_id = PCI_CLASS_BRIDGE_OTHER; k->revision = 0x40; - dc->reset = vt82c686b_pm_reset; - dc->desc = "PM"; + dc->reset = via_pm_reset; /* Reason: part of VIA south bridge, does not exist stand alone */ dc->user_creatable = false; dc->vmsd = &vmstate_acpi; } static const TypeInfo via_pm_info = { - .name = TYPE_VT82C686B_PM, + .name = TYPE_VIA_PM, .parent = TYPE_PCI_DEVICE, - .instance_size = sizeof(VT686PMState), - .class_init = via_pm_class_init, + .instance_size = sizeof(ViaPMState), + .abstract = true, .interfaces = (InterfaceInfo[]) { { INTERFACE_CONVENTIONAL_PCI_DEVICE }, { }, }, }; +static const ViaPMInitInfo vt82c686b_pm_init_info = { + .device_id = PCI_DEVICE_ID_VIA_82C686B_PM, +}; + +static const TypeInfo vt82c686b_pm_info = { + .name = TYPE_VT82C686B_PM, + .parent = TYPE_VIA_PM, + .class_init = via_pm_class_init, + .class_data = (void *)&vt82c686b_pm_init_info, +}; + +static const ViaPMInitInfo vt8231_pm_init_info = { + .device_id = PCI_DEVICE_ID_VIA_8231_PM, +}; + +static const TypeInfo vt8231_pm_info = { + .name = TYPE_VT8231_PM, + .parent = TYPE_VIA_PM, + .class_init = via_pm_class_init, + .class_data = (void *)&vt8231_pm_init_info, +}; + typedef struct SuperIOConfig { uint8_t regs[0x100]; @@ -424,6 +450,8 @@ static const TypeInfo via_superio_info = { static void vt82c686b_register_types(void) { type_register_static(&via_pm_info); + type_register_static(&vt82c686b_pm_info); + type_register_static(&vt8231_pm_info); type_register_static(&via_info); type_register_static(&via_superio_info); } diff --git a/include/hw/isa/vt82c686.h b/include/hw/isa/vt82c686.h index 5b0a1ffe72..9b6d610e83 100644 --- a/include/hw/isa/vt82c686.h +++ b/include/hw/isa/vt82c686.h @@ -4,6 +4,7 @@ #define TYPE_VT82C686B_ISA "vt82c686b-isa" #define TYPE_VT82C686B_SUPERIO "vt82c686b-superio" #define TYPE_VT82C686B_PM "vt82c686b-pm" +#define TYPE_VT8231_PM "vt8231-pm" #define TYPE_VIA_AC97 "via-ac97" #define TYPE_VIA_MC97 "via-mc97" diff --git a/include/hw/pci/pci_ids.h b/include/hw/pci/pci_ids.h index bd0c17dc78..ea28dcc850 100644 --- a/include/hw/pci/pci_ids.h +++ b/include/hw/pci/pci_ids.h @@ -207,9 +207,10 @@ #define PCI_DEVICE_ID_VIA_ISA_BRIDGE 0x0686 #define PCI_DEVICE_ID_VIA_IDE 0x0571 #define PCI_DEVICE_ID_VIA_UHCI 0x3038 -#define PCI_DEVICE_ID_VIA_ACPI 0x3057 +#define PCI_DEVICE_ID_VIA_82C686B_PM 0x3057 #define PCI_DEVICE_ID_VIA_AC97 0x3058 #define PCI_DEVICE_ID_VIA_MC97 0x3068 +#define PCI_DEVICE_ID_VIA_8231_PM 0x8235 #define PCI_VENDOR_ID_MARVELL 0x11ab -- cgit v1.2.3-55-g7522 From 9859ad1c4b6d6d505ce202e42fd5a74a7ef6e149 Mon Sep 17 00:00:00 2001 From: BALATON Zoltan Date: Sat, 9 Jan 2021 21:16:36 +0100 Subject: vt82c686: Simplify vt82c686b_realize() Remove unneeded variables and setting value to 0 on zero initialised data and replace check for error with error_fatal. Rationalise loop that sets PCI config header fields read only. Signed-off-by: BALATON Zoltan Reviewed-by: Philippe Mathieu-Daudé Message-Id: Signed-off-by: Philippe Mathieu-Daudé --- hw/isa/vt82c686.c | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/hw/isa/vt82c686.c b/hw/isa/vt82c686.c index 0e812c4924..7e5fa060f5 100644 --- a/hw/isa/vt82c686.c +++ b/hw/isa/vt82c686.c @@ -363,24 +363,16 @@ static void vt82c686b_isa_reset(DeviceState *dev) static void vt82c686b_realize(PCIDevice *d, Error **errp) { VT82C686BISAState *s = VT82C686B_ISA(d); - uint8_t *pci_conf; + DeviceState *dev = DEVICE(d); ISABus *isa_bus; - uint8_t *wmask; int i; - isa_bus = isa_bus_new(DEVICE(d), get_system_memory(), - pci_address_space_io(d), errp); - if (!isa_bus) { - return; - } - - pci_conf = d->config; - pci_config_set_prog_interface(pci_conf, 0x0); + isa_bus = isa_bus_new(dev, get_system_memory(), pci_address_space_io(d), + &error_fatal); - wmask = d->wmask; - for (i = 0x00; i < 0xff; i++) { - if (i <= 0x03 || (i >= 0x08 && i <= 0x3f)) { - wmask[i] = 0x00; + for (i = 0; i < PCI_CONFIG_HEADER_SIZE; i++) { + if (i < PCI_COMMAND || i >= PCI_REVISION_ID) { + d->wmask[i] = 0; } } -- cgit v1.2.3-55-g7522 From 3dc31cb849053c2748e0cf0595bd25475572b28a Mon Sep 17 00:00:00 2001 From: BALATON Zoltan Date: Sat, 9 Jan 2021 21:16:36 +0100 Subject: vt82c686: Move creation of ISA devices to the ISA bridge Currently the ISA devices that are part of the VIA south bridge, superio chip are wired up by board code. Move creation of these ISA devices to the VIA ISA bridge model so that board code does not need to access ISA bus. This also allows vt82c686b-superio to be made internal to vt82c686 which allows implementing its configuration via registers in subseqent commits. Signed-off-by: BALATON Zoltan Reviewed-by: Philippe Mathieu-Daudé Message-Id: Signed-off-by: Philippe Mathieu-Daudé --- hw/isa/vt82c686.c | 20 ++++++++++++++++++++ hw/mips/fuloong2e.c | 29 +++++------------------------ 2 files changed, 25 insertions(+), 24 deletions(-) diff --git a/hw/isa/vt82c686.c b/hw/isa/vt82c686.c index 7e5fa060f5..a37f1931ce 100644 --- a/hw/isa/vt82c686.c +++ b/hw/isa/vt82c686.c @@ -16,6 +16,11 @@ #include "hw/qdev-properties.h" #include "hw/isa/isa.h" #include "hw/isa/superio.h" +#include "hw/intc/i8259.h" +#include "hw/irq.h" +#include "hw/dma/i8257.h" +#include "hw/timer/i8254.h" +#include "hw/rtc/mc146818rtc.h" #include "migration/vmstate.h" #include "hw/isa/apm.h" #include "hw/acpi/acpi.h" @@ -307,9 +312,16 @@ OBJECT_DECLARE_SIMPLE_TYPE(VT82C686BISAState, VT82C686B_ISA) struct VT82C686BISAState { PCIDevice dev; + qemu_irq cpu_intr; SuperIOConfig superio_cfg; }; +static void via_isa_request_i8259_irq(void *opaque, int irq, int level) +{ + VT82C686BISAState *s = opaque; + qemu_set_irq(s->cpu_intr, level); +} + static void vt82c686b_write_config(PCIDevice *d, uint32_t addr, uint32_t val, int len) { @@ -365,10 +377,18 @@ static void vt82c686b_realize(PCIDevice *d, Error **errp) VT82C686BISAState *s = VT82C686B_ISA(d); DeviceState *dev = DEVICE(d); ISABus *isa_bus; + qemu_irq *isa_irq; int i; + qdev_init_gpio_out(dev, &s->cpu_intr, 1); + isa_irq = qemu_allocate_irqs(via_isa_request_i8259_irq, s, 1); isa_bus = isa_bus_new(dev, get_system_memory(), pci_address_space_io(d), &error_fatal); + isa_bus_irqs(isa_bus, i8259_init(isa_bus, *isa_irq)); + i8254_pit_init(isa_bus, 0x40, 0, NULL); + i8257_dma_init(isa_bus, 0); + isa_create_simple(isa_bus, TYPE_VT82C686B_SUPERIO); + mc146818_rtc_init(isa_bus, 2000, NULL); for (i = 0; i < PCI_CONFIG_HEADER_SIZE; i++) { if (i < PCI_COMMAND || i >= PCI_REVISION_ID) { diff --git a/hw/mips/fuloong2e.c b/hw/mips/fuloong2e.c index 94f4718147..4f61f2c873 100644 --- a/hw/mips/fuloong2e.c +++ b/hw/mips/fuloong2e.c @@ -25,9 +25,6 @@ #include "qapi/error.h" #include "cpu.h" #include "hw/clock.h" -#include "hw/intc/i8259.h" -#include "hw/dma/i8257.h" -#include "hw/isa/superio.h" #include "net/net.h" #include "hw/boards.h" #include "hw/i2c/smbus_eeprom.h" @@ -39,13 +36,13 @@ #include "qemu/log.h" #include "hw/loader.h" #include "hw/ide/pci.h" +#include "hw/qdev-properties.h" #include "elf.h" #include "hw/isa/vt82c686.h" -#include "hw/rtc/mc146818rtc.h" -#include "hw/timer/i8254.h" #include "exec/address-spaces.h" #include "sysemu/qtest.h" #include "sysemu/reset.h" +#include "sysemu/sysemu.h" #include "qemu/error-report.h" #define ENVP_PADDR 0x2000 @@ -203,26 +200,13 @@ static void main_cpu_reset(void *opaque) } static void vt82c686b_southbridge_init(PCIBus *pci_bus, int slot, qemu_irq intc, - I2CBus **i2c_bus, ISABus **p_isa_bus) + I2CBus **i2c_bus) { - qemu_irq *i8259; - ISABus *isa_bus; PCIDevice *dev; dev = pci_create_simple_multifunction(pci_bus, PCI_DEVFN(slot, 0), true, TYPE_VT82C686B_ISA); - isa_bus = ISA_BUS(qdev_get_child_bus(DEVICE(dev), "isa.0")); - assert(isa_bus); - *p_isa_bus = isa_bus; - /* Interrupt controller */ - /* The 8259 -> IP5 */ - i8259 = i8259_init(isa_bus, intc); - isa_bus_irqs(isa_bus, i8259); - /* init other devices */ - i8254_pit_init(isa_bus, 0x40, 0, NULL); - i8257_dma_init(isa_bus, 0); - /* Super I/O */ - isa_create_simple(isa_bus, TYPE_VT82C686B_SUPERIO); + qdev_connect_gpio_out(DEVICE(dev), 0, intc); dev = pci_create_simple(pci_bus, PCI_DEVFN(slot, 1), "via-ide"); pci_ide_create_devs(dev); @@ -269,7 +253,6 @@ static void mips_fuloong2e_init(MachineState *machine) uint64_t kernel_entry; PCIDevice *pci_dev; PCIBus *pci_bus; - ISABus *isa_bus; I2CBus *smbus; Clock *cpuclk; MIPSCPU *cpu; @@ -336,7 +319,7 @@ static void mips_fuloong2e_init(MachineState *machine) /* South bridge -> IP5 */ vt82c686b_southbridge_init(pci_bus, FULOONG2E_VIA_SLOT, env->irq[5], - &smbus, &isa_bus); + &smbus); /* GPU */ if (vga_interface_type != VGA_NONE) { @@ -351,8 +334,6 @@ static void mips_fuloong2e_init(MachineState *machine) spd_data = spd_data_generate(DDR, machine->ram_size); smbus_eeprom_init_one(smbus, 0x50, spd_data); - mc146818_rtc_init(isa_bus, 2000, NULL); - /* Network card: RTL8139D */ network_init(pci_bus); } -- cgit v1.2.3-55-g7522 From c953bf7118261a6af8f306108d5072b5d4efccd0 Mon Sep 17 00:00:00 2001 From: BALATON Zoltan Date: Sat, 9 Jan 2021 21:16:36 +0100 Subject: vt82c686: Remove index field of SuperIOConfig Remove the separate index value from SuperIOConfig and store the index at reg 0 which is reserved and returns 0 on read. This simplifies the object state. Signed-off-by: BALATON Zoltan Message-Id: <15b2968fd300a12d06b42368d084f6f80d3c3be5.1610223397.git.balaton@eik.bme.hu> [PMD: Split original patch in 5, this is part 1/5] Signed-off-by: Philippe Mathieu-Daudé --- hw/isa/vt82c686.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/hw/isa/vt82c686.c b/hw/isa/vt82c686.c index a37f1931ce..eebaa0d444 100644 --- a/hw/isa/vt82c686.c +++ b/hw/isa/vt82c686.c @@ -250,7 +250,6 @@ static const TypeInfo vt8231_pm_info = { typedef struct SuperIOConfig { uint8_t regs[0x100]; - uint8_t index; MemoryRegion io; } SuperIOConfig; @@ -258,14 +257,15 @@ static void superio_cfg_write(void *opaque, hwaddr addr, uint64_t data, unsigned size) { SuperIOConfig *sc = opaque; + uint8_t idx = sc->regs[0]; if (addr == 0x3f0) { /* config index register */ - sc->index = data & 0xff; + idx = data & 0xff; } else { bool can_write = true; /* 0x3f1, config data register */ - trace_via_superio_write(sc->index, data & 0xff); - switch (sc->index) { + trace_via_superio_write(idx, data & 0xff); + switch (idx) { case 0x00 ... 0xdf: case 0xe4: case 0xe5: @@ -283,7 +283,7 @@ static void superio_cfg_write(void *opaque, hwaddr addr, uint64_t data, } if (can_write) { - sc->regs[sc->index] = data & 0xff; + sc->regs[idx] = data & 0xff; } } } @@ -291,9 +291,16 @@ static void superio_cfg_write(void *opaque, hwaddr addr, uint64_t data, static uint64_t superio_cfg_read(void *opaque, hwaddr addr, unsigned size) { SuperIOConfig *sc = opaque; - uint8_t val = sc->regs[sc->index]; + uint8_t idx = sc->regs[0]; + uint8_t val = sc->regs[idx]; - trace_via_superio_read(sc->index, val); + if (addr == 0) { + return idx; + } + if (addr == 1 && idx == 0) { + val = 0; /* reading reg 0 where we store index value */ + } + trace_via_superio_read(idx, val); return val; } -- cgit v1.2.3-55-g7522 From 2b98dca9571a1019fcc97694b6220f9301dddd7d Mon Sep 17 00:00:00 2001 From: BALATON Zoltan Date: Sat, 9 Jan 2021 21:16:36 +0100 Subject: vt82c686: Reduce indentation by returning early Signed-off-by: BALATON Zoltan Message-Id: <15b2968fd300a12d06b42368d084f6f80d3c3be5.1610223397.git.balaton@eik.bme.hu> Reviewed-by: Philippe Mathieu-Daudé [PMD: Split patch original in 5, this is part 2/5] Signed-off-by: Philippe Mathieu-Daudé --- hw/isa/vt82c686.c | 47 +++++++++++++++++++++++------------------------ 1 file changed, 23 insertions(+), 24 deletions(-) diff --git a/hw/isa/vt82c686.c b/hw/isa/vt82c686.c index eebaa0d444..2f69b4d531 100644 --- a/hw/isa/vt82c686.c +++ b/hw/isa/vt82c686.c @@ -258,33 +258,32 @@ static void superio_cfg_write(void *opaque, hwaddr addr, uint64_t data, { SuperIOConfig *sc = opaque; uint8_t idx = sc->regs[0]; + bool can_write = true; if (addr == 0x3f0) { /* config index register */ idx = data & 0xff; - } else { - bool can_write = true; - /* 0x3f1, config data register */ - trace_via_superio_write(idx, data & 0xff); - switch (idx) { - case 0x00 ... 0xdf: - case 0xe4: - case 0xe5: - case 0xe9 ... 0xed: - case 0xf3: - case 0xf5: - case 0xf7: - case 0xf9 ... 0xfb: - case 0xfd ... 0xff: - can_write = false; - break; - /* case 0xe6 ... 0xe8: Should set base port of parallel and serial */ - default: - break; - - } - if (can_write) { - sc->regs[idx] = data & 0xff; - } + return; + } + /* 0x3f1, config data register */ + trace_via_superio_write(idx, data & 0xff); + switch (idx) { + case 0x00 ... 0xdf: + case 0xe4: + case 0xe5: + case 0xe9 ... 0xed: + case 0xf3: + case 0xf5: + case 0xf7: + case 0xf9 ... 0xfb: + case 0xfd ... 0xff: + can_write = false; + break; + /* case 0xe6 ... 0xe8: Should set base port of parallel and serial */ + default: + break; + } + if (can_write) { + sc->regs[idx] = data & 0xff; } } -- cgit v1.2.3-55-g7522 From b7741b7742573aff43398dd34c6bd4c6eed0fce7 Mon Sep 17 00:00:00 2001 From: BALATON Zoltan Date: Sat, 9 Jan 2021 21:16:36 +0100 Subject: vt82c686: Simplify by returning earlier By returning earlier we can remove the 'can_write' boolean variable. Signed-off-by: BALATON Zoltan Message-Id: <15b2968fd300a12d06b42368d084f6f80d3c3be5.1610223397.git.balaton@eik.bme.hu> Reviewed-by: Philippe Mathieu-Daudé [PMD: Split original patch in 5, this is part 3/5] Signed-off-by: Philippe Mathieu-Daudé --- hw/isa/vt82c686.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/hw/isa/vt82c686.c b/hw/isa/vt82c686.c index 2f69b4d531..2bd10d9101 100644 --- a/hw/isa/vt82c686.c +++ b/hw/isa/vt82c686.c @@ -258,7 +258,6 @@ static void superio_cfg_write(void *opaque, hwaddr addr, uint64_t data, { SuperIOConfig *sc = opaque; uint8_t idx = sc->regs[0]; - bool can_write = true; if (addr == 0x3f0) { /* config index register */ idx = data & 0xff; @@ -276,15 +275,13 @@ static void superio_cfg_write(void *opaque, hwaddr addr, uint64_t data, case 0xf7: case 0xf9 ... 0xfb: case 0xfd ... 0xff: - can_write = false; - break; + /* ignore write to read only registers */ + return; /* case 0xe6 ... 0xe8: Should set base port of parallel and serial */ default: break; } - if (can_write) { - sc->regs[idx] = data & 0xff; - } + sc->regs[idx] = data & 0xff; } static uint64_t superio_cfg_read(void *opaque, hwaddr addr, unsigned size) -- cgit v1.2.3-55-g7522 From 2c4c556e0616a003c37d53f005b7bc1b65b234ab Mon Sep 17 00:00:00 2001 From: BALATON Zoltan Date: Sat, 9 Jan 2021 21:16:36 +0100 Subject: vt82c686: Log superio_cfg unimplemented accesses Signed-off-by: BALATON Zoltan Message-Id: <15b2968fd300a12d06b42368d084f6f80d3c3be5.1610223397.git.balaton@eik.bme.hu> Reviewed-by: Philippe Mathieu-Daudé [PMD: Split original patch in 5, this is part 4/5] Signed-off-by: Philippe Mathieu-Daudé --- hw/isa/vt82c686.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/hw/isa/vt82c686.c b/hw/isa/vt82c686.c index 2bd10d9101..766584cabd 100644 --- a/hw/isa/vt82c686.c +++ b/hw/isa/vt82c686.c @@ -26,6 +26,7 @@ #include "hw/acpi/acpi.h" #include "hw/i2c/pm_smbus.h" #include "qapi/error.h" +#include "qemu/log.h" #include "qemu/module.h" #include "qemu/range.h" #include "qemu/timer.h" @@ -279,6 +280,8 @@ static void superio_cfg_write(void *opaque, hwaddr addr, uint64_t data, return; /* case 0xe6 ... 0xe8: Should set base port of parallel and serial */ default: + qemu_log_mask(LOG_UNIMP, + "via_superio_cfg: unimplemented register 0x%x\n", idx); break; } sc->regs[idx] = data & 0xff; -- cgit v1.2.3-55-g7522 From cc2b4550115baf77d556341f17eb464d18953cee Mon Sep 17 00:00:00 2001 From: BALATON Zoltan Date: Sat, 9 Jan 2021 21:16:36 +0100 Subject: vt82c686: Fix superio_cfg_{read,write}() functions These functions are memory region callbacks so we have to check against relative address not the mapped address. Signed-off-by: BALATON Zoltan Message-Id: <15b2968fd300a12d06b42368d084f6f80d3c3be5.1610223397.git.balaton@eik.bme.hu> [PMD: Split original patch in 5, this is part 5/5] Signed-off-by: Philippe Mathieu-Daudé --- hw/isa/vt82c686.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/hw/isa/vt82c686.c b/hw/isa/vt82c686.c index 766584cabd..5db9b1706c 100644 --- a/hw/isa/vt82c686.c +++ b/hw/isa/vt82c686.c @@ -260,12 +260,13 @@ static void superio_cfg_write(void *opaque, hwaddr addr, uint64_t data, SuperIOConfig *sc = opaque; uint8_t idx = sc->regs[0]; - if (addr == 0x3f0) { /* config index register */ - idx = data & 0xff; + if (addr == 0) { /* config index register */ + sc->regs[0] = data; return; } - /* 0x3f1, config data register */ - trace_via_superio_write(idx, data & 0xff); + + /* config data register */ + trace_via_superio_write(idx, data); switch (idx) { case 0x00 ... 0xdf: case 0xe4: @@ -284,7 +285,7 @@ static void superio_cfg_write(void *opaque, hwaddr addr, uint64_t data, "via_superio_cfg: unimplemented register 0x%x\n", idx); break; } - sc->regs[idx] = data & 0xff; + sc->regs[idx] = data; } static uint64_t superio_cfg_read(void *opaque, hwaddr addr, unsigned size) -- cgit v1.2.3-55-g7522