MIPS queue for January 29th, 2020

-----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1
 
 iQEcBAABAgAGBQJeMc8XAAoJENSXKoln91pl81IH/iKPa2z/zOtFK9V8puqjVf0F
 2N9EmoTtoPFDTsmCcVt5c1YbDJjvWzxFYGDFnVJd/NjAnnCYKPHFWNJcpUQbAwlm
 o5rEyTa3kM0VnGlRpiAZOsWPh5SIGy1Yzm0Qo+K1vsLTbN7vaWTn/8HsgDx/O2a6
 YHIghfGBsgG0onoVElHNl7xtMmb49P6DMKrHl9OhRgWAhpv169yY5eynv0Igb9Lw
 rtqGMJJW+s4FWbpKtF5CUM4GsijbGZYLfVyMaVriyXKKJsqZbBZcRTczZ9nDXB7X
 2XLUkBA5ItVMBkorwc7kyK8DjAi+dSGq3aQztsImrAI/1R3Jmwyaa4K5sYwW3Z8=
 =mGuu
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/amarkovic/tags/mips-queue-jan-29-2020' into staging

MIPS queue for January 29th, 2020

# gpg: Signature made Wed 29 Jan 2020 18:29:43 GMT
# gpg:                using RSA key D4972A8967F75A65
# gpg: Good signature from "Aleksandar Markovic <amarkovic@wavecomp.com>" [full]
# Primary key fingerprint: 8526 FBF1 5DA3 811F 4A01  DD75 D497 2A89 67F7 5A65

* remotes/amarkovic/tags/mips-queue-jan-29-2020:
  target/mips: Add implementation of GINVT instruction
  target/mips: Amend CP0 WatchHi register implementation
  hw/core/loader: Let load_elf() populate a field with CPU-specific flags
  target/mips: semihosting: Remove 'uhi_done' label in helper_do_semihosting()
  disas: Add a field for target-dependant data to disassemble_info
  target/mips: Rectify documentation on deprecating MIPS r4k machine

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2020-01-30 14:18:45 +00:00
commit 204aa60b37
51 changed files with 356 additions and 121 deletions

View File

@ -1409,6 +1409,16 @@ const struct mips_opcode mips_builtin_opcodes[] =
{"dvp", "t", 0x41600024, 0xffe0ffff, TRAP|WR_t, 0, I32R6}, {"dvp", "t", 0x41600024, 0xffe0ffff, TRAP|WR_t, 0, I32R6},
{"evp", "", 0x41600004, 0xffffffff, TRAP, 0, I32R6}, {"evp", "", 0x41600004, 0xffffffff, TRAP, 0, I32R6},
{"evp", "t", 0x41600004, 0xffe0ffff, TRAP|WR_t, 0, I32R6}, {"evp", "t", 0x41600004, 0xffe0ffff, TRAP|WR_t, 0, I32R6},
{"ginvi", "v", 0x7c00003d, 0xfc1ffcff, TRAP | INSN_TLB, 0, I32R6},
{"ginvt", "v", 0x7c0000bd, 0xfc1ffcff, TRAP | INSN_TLB, 0, I32R6},
{"crc32b", "t,v,t", 0x7c00000f, 0xfc00ff3f, WR_d | RD_s | RD_t, 0, I32R6},
{"crc32h", "t,v,t", 0x7c00004f, 0xfc00ff3f, WR_d | RD_s | RD_t, 0, I32R6},
{"crc32w", "t,v,t", 0x7c00008f, 0xfc00ff3f, WR_d | RD_s | RD_t, 0, I32R6},
{"crc32d", "t,v,t", 0x7c0000cf, 0xfc00ff3f, WR_d | RD_s | RD_t, 0, I64R6},
{"crc32cb", "t,v,t", 0x7c00010f, 0xfc00ff3f, WR_d | RD_s | RD_t, 0, I32R6},
{"crc32ch", "t,v,t", 0x7c00014f, 0xfc00ff3f, WR_d | RD_s | RD_t, 0, I32R6},
{"crc32cw", "t,v,t", 0x7c00018f, 0xfc00ff3f, WR_d | RD_s | RD_t, 0, I32R6},
{"crc32cd", "t,v,t", 0x7c0001cf, 0xfc00ff3f, WR_d | RD_s | RD_t, 0, I64R6},
/* MSA */ /* MSA */
{"sll.b", "+d,+e,+f", 0x7800000d, 0xffe0003f, WR_VD|RD_VS|RD_VT, 0, MSA}, {"sll.b", "+d,+e,+f", 0x7800000d, 0xffe0003f, WR_VD|RD_VS|RD_VT, 0, MSA},

View File

@ -115,7 +115,7 @@ static void clipper_init(MachineState *machine)
exit(1); exit(1);
} }
size = load_elf(palcode_filename, NULL, cpu_alpha_superpage_to_phys, size = load_elf(palcode_filename, NULL, cpu_alpha_superpage_to_phys,
NULL, &palcode_entry, &palcode_low, &palcode_high, NULL, &palcode_entry, &palcode_low, &palcode_high, NULL,
0, EM_ALPHA, 0, 0); 0, EM_ALPHA, 0, 0);
if (size < 0) { if (size < 0) {
error_report("could not load palcode '%s'", palcode_filename); error_report("could not load palcode '%s'", palcode_filename);
@ -134,7 +134,7 @@ static void clipper_init(MachineState *machine)
uint64_t param_offset; uint64_t param_offset;
size = load_elf(kernel_filename, NULL, cpu_alpha_superpage_to_phys, size = load_elf(kernel_filename, NULL, cpu_alpha_superpage_to_phys,
NULL, &kernel_entry, &kernel_low, &kernel_high, NULL, &kernel_entry, &kernel_low, &kernel_high, NULL,
0, EM_ALPHA, 0, 0); 0, EM_ALPHA, 0, 0);
if (size < 0) { if (size < 0) {
error_report("could not load kernel '%s'", kernel_filename); error_report("could not load kernel '%s'", kernel_filename);

View File

@ -331,7 +331,7 @@ void armv7m_load_kernel(ARMCPU *cpu, const char *kernel_filename, int mem_size)
if (kernel_filename) { if (kernel_filename) {
image_size = load_elf_as(kernel_filename, NULL, NULL, NULL, image_size = load_elf_as(kernel_filename, NULL, NULL, NULL,
&entry, &lowaddr, &entry, &lowaddr, NULL,
NULL, big_endian, EM_ARM, 1, 0, as); NULL, big_endian, EM_ARM, 1, 0, as);
if (image_size < 0) { if (image_size < 0) {
image_size = load_image_targphys_as(kernel_filename, 0, image_size = load_image_targphys_as(kernel_filename, 0,

View File

@ -903,7 +903,7 @@ static int64_t arm_load_elf(struct arm_boot_info *info, uint64_t *pentry,
} }
ret = load_elf_as(info->kernel_filename, NULL, NULL, NULL, ret = load_elf_as(info->kernel_filename, NULL, NULL, NULL,
pentry, lowaddr, highaddr, big_endian, elf_machine, pentry, lowaddr, highaddr, NULL, big_endian, elf_machine,
1, data_swab, as); 1, data_swab, as);
if (ret <= 0) { if (ret <= 0) {
/* The header loaded but the image didn't */ /* The header loaded but the image didn't */

View File

@ -140,7 +140,7 @@ static void generic_loader_realize(DeviceState *dev, Error **errp)
if (!s->force_raw) { if (!s->force_raw) {
size = load_elf_as(s->file, NULL, NULL, NULL, &entry, NULL, NULL, size = load_elf_as(s->file, NULL, NULL, NULL, &entry, NULL, NULL,
big_endian, 0, 0, 0, as); NULL, big_endian, 0, 0, 0, as);
if (size < 0) { if (size < 0) {
size = load_uimage_as(s->file, &entry, NULL, NULL, NULL, NULL, size = load_uimage_as(s->file, &entry, NULL, NULL, NULL, NULL,

View File

@ -406,12 +406,12 @@ int load_elf(const char *filename,
uint64_t (*elf_note_fn)(void *, void *, bool), uint64_t (*elf_note_fn)(void *, void *, bool),
uint64_t (*translate_fn)(void *, uint64_t), uint64_t (*translate_fn)(void *, uint64_t),
void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr, void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr,
uint64_t *highaddr, int big_endian, int elf_machine, uint64_t *highaddr, uint32_t *pflags, int big_endian,
int clear_lsb, int data_swab) int elf_machine, int clear_lsb, int data_swab)
{ {
return load_elf_as(filename, elf_note_fn, translate_fn, translate_opaque, return load_elf_as(filename, elf_note_fn, translate_fn, translate_opaque,
pentry, lowaddr, highaddr, big_endian, elf_machine, pentry, lowaddr, highaddr, pflags, big_endian,
clear_lsb, data_swab, NULL); elf_machine, clear_lsb, data_swab, NULL);
} }
/* return < 0 if error, otherwise the number of bytes loaded in memory */ /* return < 0 if error, otherwise the number of bytes loaded in memory */
@ -419,12 +419,12 @@ int load_elf_as(const char *filename,
uint64_t (*elf_note_fn)(void *, void *, bool), uint64_t (*elf_note_fn)(void *, void *, bool),
uint64_t (*translate_fn)(void *, uint64_t), uint64_t (*translate_fn)(void *, uint64_t),
void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr, void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr,
uint64_t *highaddr, int big_endian, int elf_machine, uint64_t *highaddr, uint32_t *pflags, int big_endian,
int clear_lsb, int data_swab, AddressSpace *as) int elf_machine, int clear_lsb, int data_swab, AddressSpace *as)
{ {
return load_elf_ram(filename, elf_note_fn, translate_fn, translate_opaque, return load_elf_ram(filename, elf_note_fn, translate_fn, translate_opaque,
pentry, lowaddr, highaddr, big_endian, elf_machine, pentry, lowaddr, highaddr, pflags, big_endian,
clear_lsb, data_swab, as, true); elf_machine, clear_lsb, data_swab, as, true);
} }
/* return < 0 if error, otherwise the number of bytes loaded in memory */ /* return < 0 if error, otherwise the number of bytes loaded in memory */
@ -432,13 +432,13 @@ int load_elf_ram(const char *filename,
uint64_t (*elf_note_fn)(void *, void *, bool), uint64_t (*elf_note_fn)(void *, void *, bool),
uint64_t (*translate_fn)(void *, uint64_t), uint64_t (*translate_fn)(void *, uint64_t),
void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr, void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr,
uint64_t *highaddr, int big_endian, int elf_machine, uint64_t *highaddr, uint32_t *pflags, int big_endian,
int clear_lsb, int data_swab, AddressSpace *as, int elf_machine, int clear_lsb, int data_swab,
bool load_rom) AddressSpace *as, bool load_rom)
{ {
return load_elf_ram_sym(filename, elf_note_fn, return load_elf_ram_sym(filename, elf_note_fn,
translate_fn, translate_opaque, translate_fn, translate_opaque,
pentry, lowaddr, highaddr, big_endian, pentry, lowaddr, highaddr, pflags, big_endian,
elf_machine, clear_lsb, data_swab, as, elf_machine, clear_lsb, data_swab, as,
load_rom, NULL); load_rom, NULL);
} }
@ -448,8 +448,9 @@ int load_elf_ram_sym(const char *filename,
uint64_t (*elf_note_fn)(void *, void *, bool), uint64_t (*elf_note_fn)(void *, void *, bool),
uint64_t (*translate_fn)(void *, uint64_t), uint64_t (*translate_fn)(void *, uint64_t),
void *translate_opaque, uint64_t *pentry, void *translate_opaque, uint64_t *pentry,
uint64_t *lowaddr, uint64_t *highaddr, int big_endian, uint64_t *lowaddr, uint64_t *highaddr, uint32_t *pflags,
int elf_machine, int clear_lsb, int data_swab, int big_endian, int elf_machine,
int clear_lsb, int data_swab,
AddressSpace *as, bool load_rom, symbol_fn_t sym_cb) AddressSpace *as, bool load_rom, symbol_fn_t sym_cb)
{ {
int fd, data_order, target_data_order, must_swab, ret = ELF_LOAD_FAILED; int fd, data_order, target_data_order, must_swab, ret = ELF_LOAD_FAILED;
@ -490,13 +491,13 @@ int load_elf_ram_sym(const char *filename,
if (e_ident[EI_CLASS] == ELFCLASS64) { if (e_ident[EI_CLASS] == ELFCLASS64) {
ret = load_elf64(filename, fd, elf_note_fn, ret = load_elf64(filename, fd, elf_note_fn,
translate_fn, translate_opaque, must_swab, translate_fn, translate_opaque, must_swab,
pentry, lowaddr, highaddr, elf_machine, clear_lsb, pentry, lowaddr, highaddr, pflags, elf_machine,
data_swab, as, load_rom, sym_cb); clear_lsb, data_swab, as, load_rom, sym_cb);
} else { } else {
ret = load_elf32(filename, fd, elf_note_fn, ret = load_elf32(filename, fd, elf_note_fn,
translate_fn, translate_opaque, must_swab, translate_fn, translate_opaque, must_swab,
pentry, lowaddr, highaddr, elf_machine, clear_lsb, pentry, lowaddr, highaddr, pflags, elf_machine,
data_swab, as, load_rom, sym_cb); clear_lsb, data_swab, as, load_rom, sym_cb);
} }
fail: fail:

View File

@ -76,7 +76,7 @@ void cris_load_image(CRISCPU *cpu, struct cris_load_info *li)
devboard SDK. */ devboard SDK. */
image_size = load_elf(li->image_filename, NULL, image_size = load_elf(li->image_filename, NULL,
translate_kernel_address, NULL, translate_kernel_address, NULL,
&entry, NULL, &high, 0, EM_CRIS, 0, 0); &entry, NULL, &high, NULL, 0, EM_CRIS, 0, 0);
li->entry = entry; li->entry = entry;
if (image_size < 0) { if (image_size < 0) {
/* Takes a kimage from the axis devboard SDK. */ /* Takes a kimage from the axis devboard SDK. */

View File

@ -155,7 +155,7 @@ static void machine_hppa_init(MachineState *machine)
} }
size = load_elf(firmware_filename, NULL, NULL, NULL, size = load_elf(firmware_filename, NULL, NULL, NULL,
&firmware_entry, &firmware_low, &firmware_high, &firmware_entry, &firmware_low, &firmware_high, NULL,
true, EM_PARISC, 0, 0); true, EM_PARISC, 0, 0);
/* Unfortunately, load_elf sign-extends reading elf32. */ /* Unfortunately, load_elf sign-extends reading elf32. */
@ -184,7 +184,7 @@ static void machine_hppa_init(MachineState *machine)
/* Load kernel */ /* Load kernel */
if (kernel_filename) { if (kernel_filename) {
size = load_elf(kernel_filename, NULL, &cpu_hppa_to_phys, size = load_elf(kernel_filename, NULL, &cpu_hppa_to_phys,
NULL, &kernel_entry, &kernel_low, &kernel_high, NULL, &kernel_entry, &kernel_low, &kernel_high, NULL,
true, EM_PARISC, 0, 0); true, EM_PARISC, 0, 0);
/* Unfortunately, load_elf sign-extends reading elf32. */ /* Unfortunately, load_elf sign-extends reading elf32. */

View File

@ -199,7 +199,7 @@ int load_multiboot(FWCfgState *fw_cfg,
} }
kernel_size = load_elf(kernel_filename, NULL, NULL, NULL, &elf_entry, kernel_size = load_elf(kernel_filename, NULL, NULL, NULL, &elf_entry,
&elf_low, &elf_high, 0, I386_ELF_MACHINE, &elf_low, &elf_high, NULL, 0, I386_ELF_MACHINE,
0, 0); 0, 0);
if (kernel_size < 0) { if (kernel_size < 0) {
error_report("Error while loading elf kernel"); error_report("Error while loading elf kernel");

View File

@ -413,7 +413,7 @@ static bool load_elfboot(const char *kernel_filename,
uint64_t elf_note_type = XEN_ELFNOTE_PHYS32_ENTRY; uint64_t elf_note_type = XEN_ELFNOTE_PHYS32_ENTRY;
kernel_size = load_elf(kernel_filename, read_pvh_start_addr, kernel_size = load_elf(kernel_filename, read_pvh_start_addr,
NULL, &elf_note_type, &elf_entry, NULL, &elf_note_type, &elf_entry,
&elf_low, &elf_high, 0, I386_ELF_MACHINE, &elf_low, &elf_high, NULL, 0, I386_ELF_MACHINE,
0, 0); 0, 0);
if (kernel_size < 0) { if (kernel_size < 0) {

View File

@ -138,7 +138,7 @@ static void lm32_evr_init(MachineState *machine)
int kernel_size; int kernel_size;
kernel_size = load_elf(kernel_filename, NULL, NULL, NULL, kernel_size = load_elf(kernel_filename, NULL, NULL, NULL,
&entry, NULL, NULL, &entry, NULL, NULL, NULL,
1, EM_LATTICEMICO32, 0, 0); 1, EM_LATTICEMICO32, 0, 0);
reset_info->bootstrap_pc = entry; reset_info->bootstrap_pc = entry;
@ -232,7 +232,7 @@ static void lm32_uclinux_init(MachineState *machine)
int kernel_size; int kernel_size;
kernel_size = load_elf(kernel_filename, NULL, NULL, NULL, kernel_size = load_elf(kernel_filename, NULL, NULL, NULL,
&entry, NULL, NULL, &entry, NULL, NULL, NULL,
1, EM_LATTICEMICO32, 0, 0); 1, EM_LATTICEMICO32, 0, 0);
reset_info->bootstrap_pc = entry; reset_info->bootstrap_pc = entry;

View File

@ -177,7 +177,7 @@ milkymist_init(MachineState *machine)
/* Boots a kernel elf binary. */ /* Boots a kernel elf binary. */
kernel_size = load_elf(kernel_filename, NULL, NULL, NULL, kernel_size = load_elf(kernel_filename, NULL, NULL, NULL,
&entry, NULL, NULL, &entry, NULL, NULL, NULL,
1, EM_LATTICEMICO32, 0, 0); 1, EM_LATTICEMICO32, 0, 0);
reset_info->bootstrap_pc = entry; reset_info->bootstrap_pc = entry;

View File

@ -65,7 +65,7 @@ static void an5206_init(MachineState *machine)
} }
kernel_size = load_elf(kernel_filename, NULL, NULL, NULL, &elf_entry, kernel_size = load_elf(kernel_filename, NULL, NULL, NULL, &elf_entry,
NULL, NULL, 1, EM_68K, 0, 0); NULL, NULL, NULL, 1, EM_68K, 0, 0);
entry = elf_entry; entry = elf_entry;
if (kernel_size < 0) { if (kernel_size < 0) {
kernel_size = load_uimage(kernel_filename, &entry, NULL, NULL, kernel_size = load_uimage(kernel_filename, &entry, NULL, NULL,

View File

@ -329,7 +329,7 @@ static void mcf5208evb_init(MachineState *machine)
} }
kernel_size = load_elf(kernel_filename, NULL, NULL, NULL, &elf_entry, kernel_size = load_elf(kernel_filename, NULL, NULL, NULL, &elf_entry,
NULL, NULL, 1, EM_68K, 0, 0); NULL, NULL, NULL, 1, EM_68K, 0, 0);
entry = elf_entry; entry = elf_entry;
if (kernel_size < 0) { if (kernel_size < 0) {
kernel_size = load_uimage(kernel_filename, &entry, NULL, NULL, kernel_size = load_uimage(kernel_filename, &entry, NULL, NULL,

View File

@ -342,7 +342,7 @@ static void q800_init(MachineState *machine)
if (linux_boot) { if (linux_boot) {
uint64_t high; uint64_t high;
kernel_size = load_elf(kernel_filename, NULL, NULL, NULL, kernel_size = load_elf(kernel_filename, NULL, NULL, NULL,
&elf_entry, NULL, &high, 1, &elf_entry, NULL, &high, NULL, 1,
EM_68K, 0, 0); EM_68K, 0, 0);
if (kernel_size < 0) { if (kernel_size < 0) {
error_report("could not load kernel '%s'", kernel_filename); error_report("could not load kernel '%s'", kernel_filename);

View File

@ -145,13 +145,13 @@ void microblaze_load_kernel(MicroBlazeCPU *cpu, hwaddr ddr_base,
/* Boots a kernel elf binary. */ /* Boots a kernel elf binary. */
kernel_size = load_elf(kernel_filename, NULL, NULL, NULL, kernel_size = load_elf(kernel_filename, NULL, NULL, NULL,
&entry, &low, &high, &entry, &low, &high, NULL,
big_endian, EM_MICROBLAZE, 0, 0); big_endian, EM_MICROBLAZE, 0, 0);
base32 = entry; base32 = entry;
if (base32 == 0xc0000000) { if (base32 == 0xc0000000) {
kernel_size = load_elf(kernel_filename, NULL, kernel_size = load_elf(kernel_filename, NULL,
translate_kernel_address, NULL, translate_kernel_address, NULL,
&entry, NULL, NULL, &entry, NULL, NULL, NULL,
big_endian, EM_MICROBLAZE, 0, 0); big_endian, EM_MICROBLAZE, 0, 0);
} }
/* Always boot into physical ram. */ /* Always boot into physical ram. */

View File

@ -119,7 +119,7 @@ static int64_t load_kernel(CPUMIPSState *env)
cpu_mips_kseg0_to_phys, NULL, cpu_mips_kseg0_to_phys, NULL,
(uint64_t *)&kernel_entry, (uint64_t *)&kernel_entry,
(uint64_t *)&kernel_low, (uint64_t *)&kernel_high, (uint64_t *)&kernel_low, (uint64_t *)&kernel_high,
0, EM_MIPS, 1, 0); NULL, 0, EM_MIPS, 1, 0);
if (kernel_size < 0) { if (kernel_size < 0) {
error_report("could not load kernel '%s': %s", error_report("could not load kernel '%s': %s",
loaderparams.kernel_filename, loaderparams.kernel_filename,

View File

@ -1039,7 +1039,8 @@ static int64_t load_kernel(void)
kernel_size = load_elf(loaderparams.kernel_filename, NULL, kernel_size = load_elf(loaderparams.kernel_filename, NULL,
cpu_mips_kseg0_to_phys, NULL, cpu_mips_kseg0_to_phys, NULL,
(uint64_t *)&kernel_entry, NULL, (uint64_t *)&kernel_entry, NULL,
(uint64_t *)&kernel_high, big_endian, EM_MIPS, 1, 0); (uint64_t *)&kernel_high, NULL, big_endian, EM_MIPS,
1, 0);
if (kernel_size < 0) { if (kernel_size < 0) {
error_report("could not load kernel '%s': %s", error_report("could not load kernel '%s': %s",
loaderparams.kernel_filename, loaderparams.kernel_filename,

View File

@ -74,7 +74,7 @@ static int64_t load_kernel(void)
kernel_size = load_elf(loaderparams.kernel_filename, NULL, kernel_size = load_elf(loaderparams.kernel_filename, NULL,
cpu_mips_kseg0_to_phys, NULL, cpu_mips_kseg0_to_phys, NULL,
(uint64_t *)&entry, NULL, (uint64_t *)&entry, NULL,
(uint64_t *)&kernel_high, big_endian, (uint64_t *)&kernel_high, NULL, big_endian,
EM_MIPS, 1, 0); EM_MIPS, 1, 0);
if (kernel_size >= 0) { if (kernel_size >= 0) {
if ((entry & ~0x7fffffffULL) == 0x80000000) { if ((entry & ~0x7fffffffULL) == 0x80000000) {

View File

@ -98,7 +98,7 @@ static int64_t load_kernel(void)
kernel_size = load_elf(loaderparams.kernel_filename, NULL, kernel_size = load_elf(loaderparams.kernel_filename, NULL,
cpu_mips_kseg0_to_phys, NULL, cpu_mips_kseg0_to_phys, NULL,
(uint64_t *)&entry, NULL, (uint64_t *)&entry, NULL,
(uint64_t *)&kernel_high, big_endian, (uint64_t *)&kernel_high, NULL, big_endian,
EM_MIPS, 1, 0); EM_MIPS, 1, 0);
if (kernel_size >= 0) { if (kernel_size >= 0) {
if ((entry & ~0x7fffffffULL) == 0x80000000) { if ((entry & ~0x7fffffffULL) == 0x80000000) {

View File

@ -58,7 +58,7 @@ static void load_kernel(MoxieCPU *cpu, LoaderParams *loader_params)
ram_addr_t initrd_offset; ram_addr_t initrd_offset;
kernel_size = load_elf(loader_params->kernel_filename, NULL, NULL, NULL, kernel_size = load_elf(loader_params->kernel_filename, NULL, NULL, NULL,
&entry, &kernel_low, &kernel_high, 1, EM_MOXIE, &entry, &kernel_low, &kernel_high, NULL, 1, EM_MOXIE,
0, 0); 0, 0);
if (kernel_size <= 0) { if (kernel_size <= 0) {

View File

@ -147,7 +147,7 @@ void nios2_load_kernel(Nios2CPU *cpu, hwaddr ddr_base,
/* Boots a kernel elf binary. */ /* Boots a kernel elf binary. */
kernel_size = load_elf(kernel_filename, NULL, NULL, NULL, kernel_size = load_elf(kernel_filename, NULL, NULL, NULL,
&entry, &low, &high, &entry, &low, &high, NULL,
big_endian, EM_ALTERA_NIOS2, 0, 0); big_endian, EM_ALTERA_NIOS2, 0, 0);
if ((uint32_t)entry == 0xc0000000) { if ((uint32_t)entry == 0xc0000000) {
/* /*
@ -158,7 +158,7 @@ void nios2_load_kernel(Nios2CPU *cpu, hwaddr ddr_base,
*/ */
kernel_size = load_elf(kernel_filename, NULL, kernel_size = load_elf(kernel_filename, NULL,
translate_kernel_address, NULL, translate_kernel_address, NULL,
&entry, NULL, NULL, &entry, NULL, NULL, NULL,
big_endian, EM_ALTERA_NIOS2, 0, 0); big_endian, EM_ALTERA_NIOS2, 0, 0);
boot_info.bootstrap_pc = ddr_base + 0xc0000000 + boot_info.bootstrap_pc = ddr_base + 0xc0000000 +
(entry & 0x07ffffff); (entry & 0x07ffffff);

View File

@ -98,7 +98,7 @@ static void openrisc_load_kernel(ram_addr_t ram_size,
if (kernel_filename && !qtest_enabled()) { if (kernel_filename && !qtest_enabled()) {
kernel_size = load_elf(kernel_filename, NULL, NULL, NULL, kernel_size = load_elf(kernel_filename, NULL, NULL, NULL,
&elf_entry, NULL, NULL, 1, EM_OPENRISC, &elf_entry, NULL, NULL, NULL, 1, EM_OPENRISC,
1, 0); 1, 0);
entry = elf_entry; entry = elf_entry;
if (kernel_size < 0) { if (kernel_size < 0) {

View File

@ -335,7 +335,8 @@ static void raven_realize(PCIDevice *d, Error **errp)
if (filename) { if (filename) {
if (s->elf_machine != EM_NONE) { if (s->elf_machine != EM_NONE) {
bios_size = load_elf(filename, NULL, NULL, NULL, NULL, bios_size = load_elf(filename, NULL, NULL, NULL, NULL,
NULL, NULL, 1, s->elf_machine, 0, 0); NULL, NULL, NULL, 1, s->elf_machine,
0, 0);
} }
if (bios_size < 0) { if (bios_size < 0) {
bios_size = get_image_size(filename); bios_size = get_image_size(filename);

View File

@ -1049,7 +1049,7 @@ void ppce500_init(MachineState *machine)
filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, payload_name); filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, payload_name);
payload_size = load_elf(filename, NULL, NULL, NULL, payload_size = load_elf(filename, NULL, NULL, NULL,
&bios_entry, &loadaddr, NULL, &bios_entry, &loadaddr, NULL, NULL,
1, PPC_ELF_MACHINE, 0, 0); 1, PPC_ELF_MACHINE, 0, 0);
if (payload_size < 0) { if (payload_size < 0) {
/* /*

View File

@ -168,7 +168,7 @@ static void ppc_core99_init(MachineState *machine)
/* Load OpenBIOS (ELF) */ /* Load OpenBIOS (ELF) */
if (filename) { if (filename) {
bios_size = load_elf(filename, NULL, NULL, NULL, NULL, bios_size = load_elf(filename, NULL, NULL, NULL, NULL,
NULL, NULL, 1, PPC_ELF_MACHINE, 0, 0); NULL, NULL, NULL, 1, PPC_ELF_MACHINE, 0, 0);
g_free(filename); g_free(filename);
} else { } else {
@ -192,7 +192,7 @@ static void ppc_core99_init(MachineState *machine)
kernel_size = load_elf(kernel_filename, NULL, kernel_size = load_elf(kernel_filename, NULL,
translate_kernel_address, NULL, translate_kernel_address, NULL,
NULL, &lowaddr, NULL, 1, PPC_ELF_MACHINE, NULL, &lowaddr, NULL, NULL, 1, PPC_ELF_MACHINE,
0, 0); 0, 0);
if (kernel_size < 0) if (kernel_size < 0)
kernel_size = load_aout(kernel_filename, kernel_base, kernel_size = load_aout(kernel_filename, kernel_base,

View File

@ -143,7 +143,7 @@ static void ppc_heathrow_init(MachineState *machine)
/* Load OpenBIOS (ELF) */ /* Load OpenBIOS (ELF) */
if (filename) { if (filename) {
bios_size = load_elf(filename, NULL, 0, NULL, NULL, NULL, NULL, bios_size = load_elf(filename, NULL, 0, NULL, NULL, NULL, NULL, NULL,
1, PPC_ELF_MACHINE, 0, 0); 1, PPC_ELF_MACHINE, 0, 0);
g_free(filename); g_free(filename);
} else { } else {
@ -166,7 +166,7 @@ static void ppc_heathrow_init(MachineState *machine)
kernel_base = KERNEL_LOAD_ADDR; kernel_base = KERNEL_LOAD_ADDR;
kernel_size = load_elf(kernel_filename, NULL, kernel_size = load_elf(kernel_filename, NULL,
translate_kernel_address, NULL, translate_kernel_address, NULL,
NULL, &lowaddr, NULL, 1, PPC_ELF_MACHINE, NULL, &lowaddr, NULL, NULL, 1, PPC_ELF_MACHINE,
0, 0); 0, 0);
if (kernel_size < 0) if (kernel_size < 0)
kernel_size = load_aout(kernel_filename, kernel_base, kernel_size = load_aout(kernel_filename, kernel_base,

View File

@ -253,7 +253,7 @@ static void bamboo_init(MachineState *machine)
NULL, NULL); NULL, NULL);
if (success < 0) { if (success < 0) {
success = load_elf(kernel_filename, NULL, NULL, NULL, &elf_entry, success = load_elf(kernel_filename, NULL, NULL, NULL, &elf_entry,
&elf_lowaddr, NULL, 1, PPC_ELF_MACHINE, &elf_lowaddr, NULL, NULL, 1, PPC_ELF_MACHINE,
0, 0); 0, 0);
entry = elf_entry; entry = elf_entry;
loadaddr = elf_lowaddr; loadaddr = elf_lowaddr;

View File

@ -439,7 +439,8 @@ static void sam460ex_init(MachineState *machine)
success = load_elf(machine->kernel_filename, NULL, success = load_elf(machine->kernel_filename, NULL,
NULL, NULL, &elf_entry, NULL, NULL, &elf_entry,
&elf_lowaddr, NULL, 1, PPC_ELF_MACHINE, 0, 0); &elf_lowaddr, NULL, NULL, 1, PPC_ELF_MACHINE, 0,
0);
entry = elf_entry; entry = elf_entry;
loadaddr = elf_lowaddr; loadaddr = elf_lowaddr;
} }

View File

@ -2895,13 +2895,13 @@ static void spapr_machine_init(MachineState *machine)
spapr->kernel_size = load_elf(kernel_filename, NULL, spapr->kernel_size = load_elf(kernel_filename, NULL,
translate_kernel_address, NULL, translate_kernel_address, NULL,
NULL, &lowaddr, NULL, 1, NULL, &lowaddr, NULL, NULL, 1,
PPC_ELF_MACHINE, 0, 0); PPC_ELF_MACHINE, 0, 0);
if (spapr->kernel_size == ELF_LOAD_WRONG_ENDIAN) { if (spapr->kernel_size == ELF_LOAD_WRONG_ENDIAN) {
spapr->kernel_size = load_elf(kernel_filename, NULL, spapr->kernel_size = load_elf(kernel_filename, NULL,
translate_kernel_address, NULL, NULL, translate_kernel_address, NULL, NULL,
&lowaddr, NULL, 0, PPC_ELF_MACHINE, &lowaddr, NULL, NULL, 0,
0, 0); PPC_ELF_MACHINE, 0, 0);
spapr->kernel_le = spapr->kernel_size > 0; spapr->kernel_le = spapr->kernel_size > 0;
} }
if (spapr->kernel_size < 0) { if (spapr->kernel_size < 0) {

View File

@ -259,7 +259,7 @@ static void virtex_init(MachineState *machine)
/* Boots a kernel elf binary. */ /* Boots a kernel elf binary. */
kernel_size = load_elf(kernel_filename, NULL, NULL, NULL, kernel_size = load_elf(kernel_filename, NULL, NULL, NULL,
&entry, &low, &high, 1, PPC_ELF_MACHINE, &entry, &low, &high, NULL, 1, PPC_ELF_MACHINE,
0, 0); 0, 0);
boot_info.bootstrap_pc = entry & 0x00ffffff; boot_info.bootstrap_pc = entry & 0x00ffffff;

View File

@ -101,7 +101,7 @@ target_ulong riscv_load_firmware(const char *firmware_filename,
uint64_t firmware_entry, firmware_start, firmware_end; uint64_t firmware_entry, firmware_start, firmware_end;
if (load_elf(firmware_filename, NULL, NULL, NULL, &firmware_entry, if (load_elf(firmware_filename, NULL, NULL, NULL, &firmware_entry,
&firmware_start, &firmware_end, 0, EM_RISCV, 1, 0) > 0) { &firmware_start, &firmware_end, NULL, 0, EM_RISCV, 1, 0) > 0) {
return firmware_entry; return firmware_entry;
} }
@ -119,7 +119,7 @@ target_ulong riscv_load_kernel(const char *kernel_filename, symbol_fn_t sym_cb)
uint64_t kernel_entry, kernel_high; uint64_t kernel_entry, kernel_high;
if (load_elf_ram_sym(kernel_filename, NULL, NULL, NULL, if (load_elf_ram_sym(kernel_filename, NULL, NULL, NULL,
&kernel_entry, NULL, &kernel_high, 0, &kernel_entry, NULL, &kernel_high, NULL, 0,
EM_RISCV, 1, 0, NULL, true, sym_cb) > 0) { EM_RISCV, 1, 0, NULL, true, sym_cb) > 0) {
return kernel_entry; return kernel_entry;
} }

View File

@ -139,7 +139,7 @@ static void s390_ipl_realize(DeviceState *dev, Error **errp)
bios_size = load_elf(bios_filename, NULL, bios_size = load_elf(bios_filename, NULL,
bios_translate_addr, &fwbase, bios_translate_addr, &fwbase,
&ipl->bios_start_addr, NULL, NULL, 1, &ipl->bios_start_addr, NULL, NULL, NULL, 1,
EM_S390, 0, 0); EM_S390, 0, 0);
if (bios_size > 0) { if (bios_size > 0) {
/* Adjust ELF start address to final location */ /* Adjust ELF start address to final location */
@ -164,7 +164,7 @@ static void s390_ipl_realize(DeviceState *dev, Error **errp)
if (ipl->kernel) { if (ipl->kernel) {
kernel_size = load_elf(ipl->kernel, NULL, NULL, NULL, kernel_size = load_elf(ipl->kernel, NULL, NULL, NULL,
&pentry, NULL, &pentry, NULL,
NULL, 1, EM_S390, 0, 0); NULL, NULL, 1, EM_S390, 0, 0);
if (kernel_size < 0) { if (kernel_size < 0) {
kernel_size = load_image_targphys(ipl->kernel, 0, ram_size); kernel_size = load_image_targphys(ipl->kernel, 0, ram_size);
if (kernel_size < 0) { if (kernel_size < 0) {
@ -473,7 +473,8 @@ static int load_netboot_image(Error **errp)
img_size = load_elf_ram(netboot_filename, NULL, NULL, NULL, img_size = load_elf_ram(netboot_filename, NULL, NULL, NULL,
&ipl->start_addr, &ipl->start_addr,
NULL, NULL, 1, EM_S390, 0, 0, NULL, false); NULL, NULL, NULL, 1, EM_S390, 0, 0, NULL,
false);
if (img_size < 0) { if (img_size < 0) {
img_size = load_image_size(netboot_filename, ram_ptr, ram_size); img_size = load_image_size(netboot_filename, ram_ptr, ram_size);

View File

@ -297,7 +297,7 @@ static void leon3_generic_hw_init(MachineState *machine)
uint64_t entry; uint64_t entry;
kernel_size = load_elf(kernel_filename, NULL, NULL, NULL, kernel_size = load_elf(kernel_filename, NULL, NULL, NULL,
&entry, NULL, NULL, &entry, NULL, NULL, NULL,
1 /* big endian */, EM_SPARC, 0, 0); 1 /* big endian */, EM_SPARC, 0, 0);
if (kernel_size < 0) { if (kernel_size < 0) {
kernel_size = load_uimage(kernel_filename, NULL, &entry, kernel_size = load_uimage(kernel_filename, NULL, &entry,

View File

@ -270,7 +270,7 @@ static unsigned long sun4m_load_kernel(const char *kernel_filename,
#endif #endif
kernel_size = load_elf(kernel_filename, NULL, kernel_size = load_elf(kernel_filename, NULL,
translate_kernel_address, NULL, translate_kernel_address, NULL,
NULL, NULL, NULL, 1, EM_SPARC, 0, 0); NULL, NULL, NULL, NULL, 1, EM_SPARC, 0, 0);
if (kernel_size < 0) if (kernel_size < 0)
kernel_size = load_aout(kernel_filename, KERNEL_LOAD_ADDR, kernel_size = load_aout(kernel_filename, KERNEL_LOAD_ADDR,
RAM_size - KERNEL_LOAD_ADDR, bswap_needed, RAM_size - KERNEL_LOAD_ADDR, bswap_needed,
@ -721,7 +721,7 @@ static void prom_init(hwaddr addr, const char *bios_name)
if (filename) { if (filename) {
ret = load_elf(filename, NULL, ret = load_elf(filename, NULL,
translate_prom_address, &addr, NULL, translate_prom_address, &addr, NULL,
NULL, NULL, 1, EM_SPARC, 0, 0); NULL, NULL, NULL, 1, EM_SPARC, 0, 0);
if (ret < 0 || ret > PROM_SIZE_MAX) { if (ret < 0 || ret > PROM_SIZE_MAX) {
ret = load_image_targphys(filename, addr, PROM_SIZE_MAX); ret = load_image_targphys(filename, addr, PROM_SIZE_MAX);
} }

View File

@ -175,7 +175,8 @@ static uint64_t sun4u_load_kernel(const char *kernel_filename,
bswap_needed = 0; bswap_needed = 0;
#endif #endif
kernel_size = load_elf(kernel_filename, NULL, NULL, NULL, kernel_entry, kernel_size = load_elf(kernel_filename, NULL, NULL, NULL, kernel_entry,
kernel_addr, &kernel_top, 1, EM_SPARCV9, 0, 0); kernel_addr, &kernel_top, NULL, 1, EM_SPARCV9, 0,
0);
if (kernel_size < 0) { if (kernel_size < 0) {
*kernel_addr = KERNEL_LOAD_ADDR; *kernel_addr = KERNEL_LOAD_ADDR;
*kernel_entry = KERNEL_LOAD_ADDR; *kernel_entry = KERNEL_LOAD_ADDR;
@ -439,7 +440,7 @@ static void prom_init(hwaddr addr, const char *bios_name)
filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
if (filename) { if (filename) {
ret = load_elf(filename, NULL, translate_prom_address, &addr, ret = load_elf(filename, NULL, translate_prom_address, &addr,
NULL, NULL, NULL, 1, EM_SPARCV9, 0, 0); NULL, NULL, NULL, NULL, 1, EM_SPARCV9, 0, 0);
if (ret < 0 || ret > PROM_SIZE_MAX) { if (ret < 0 || ret > PROM_SIZE_MAX) {
ret = load_image_targphys(filename, addr, PROM_SIZE_MAX); ret = load_image_targphys(filename, addr, PROM_SIZE_MAX);
} }

View File

@ -42,7 +42,7 @@ static void tricore_load_kernel(CPUTriCoreState *env)
kernel_size = load_elf(tricoretb_binfo.kernel_filename, NULL, kernel_size = load_elf(tricoretb_binfo.kernel_filename, NULL,
NULL, NULL, &entry, NULL, NULL, NULL, &entry, NULL,
NULL, 0, NULL, NULL, 0,
EM_TRICORE, 1, 0); EM_TRICORE, 1, 0);
if (kernel_size <= 0) { if (kernel_size <= 0) {
error_report("no kernel file '%s'", error_report("no kernel file '%s'",

View File

@ -108,7 +108,7 @@ void xtensa_sim_load_kernel(XtensaCPU *cpu, MachineState *machine)
uint64_t elf_entry; uint64_t elf_entry;
uint64_t elf_lowaddr; uint64_t elf_lowaddr;
int success = load_elf(kernel_filename, NULL, translate_phys_addr, cpu, int success = load_elf(kernel_filename, NULL, translate_phys_addr, cpu,
&elf_entry, &elf_lowaddr, NULL, big_endian, &elf_entry, &elf_lowaddr, NULL, NULL, big_endian,
EM_XTENSA, 0, 0); EM_XTENSA, 0, 0);
if (success > 0) { if (success > 0) {

View File

@ -415,7 +415,7 @@ static void xtfpga_init(const XtfpgaBoardDesc *board, MachineState *machine)
uint64_t elf_entry; uint64_t elf_entry;
uint64_t elf_lowaddr; uint64_t elf_lowaddr;
int success = load_elf(kernel_filename, NULL, translate_phys_addr, cpu, int success = load_elf(kernel_filename, NULL, translate_phys_addr, cpu,
&elf_entry, &elf_lowaddr, NULL, be, EM_XTENSA, 0, 0); &elf_entry, &elf_lowaddr, NULL, NULL, be, EM_XTENSA, 0, 0);
if (success > 0) { if (success > 0) {
entry_point = elf_entry; entry_point = elf_entry;
} else { } else {

View File

@ -372,6 +372,9 @@ typedef struct disassemble_info {
/* Command line options specific to the target disassembler. */ /* Command line options specific to the target disassembler. */
char * disassembler_options; char * disassembler_options;
/* Field intended to be used by targets in any way they deem suitable. */
int64_t target_info;
/* Options for Capstone disassembly. */ /* Options for Capstone disassembly. */
int cap_arch; int cap_arch;
int cap_mode; int cap_mode;

View File

@ -316,7 +316,8 @@ static int glue(load_elf, SZ)(const char *name, int fd,
void *translate_opaque, void *translate_opaque,
int must_swab, uint64_t *pentry, int must_swab, uint64_t *pentry,
uint64_t *lowaddr, uint64_t *highaddr, uint64_t *lowaddr, uint64_t *highaddr,
int elf_machine, int clear_lsb, int data_swab, uint32_t *pflags, int elf_machine,
int clear_lsb, int data_swab,
AddressSpace *as, bool load_rom, AddressSpace *as, bool load_rom,
symbol_fn_t sym_cb) symbol_fn_t sym_cb)
{ {
@ -389,6 +390,9 @@ static int glue(load_elf, SZ)(const char *name, int fd,
} }
} }
if (pflags) {
*pflags = (elf_word)ehdr.e_flags;
}
if (pentry) if (pentry)
*pentry = (uint64_t)(elf_sword)ehdr.e_entry; *pentry = (uint64_t)(elf_sword)ehdr.e_entry;

View File

@ -101,6 +101,7 @@ const char *load_elf_strerror(int error);
* @pentry: Populated with program entry point. Ignored if NULL. * @pentry: Populated with program entry point. Ignored if NULL.
* @lowaddr: Populated with lowest loaded address. Ignored if NULL. * @lowaddr: Populated with lowest loaded address. Ignored if NULL.
* @highaddr: Populated with highest loaded address. Ignored if NULL. * @highaddr: Populated with highest loaded address. Ignored if NULL.
* @pflags: Populated with ELF processor-specific flags. Ignore if NULL.
* @bigendian: Expected ELF endianness. 0 for LE otherwise BE * @bigendian: Expected ELF endianness. 0 for LE otherwise BE
* @elf_machine: Expected ELF machine type * @elf_machine: Expected ELF machine type
* @clear_lsb: Set to mask off LSB of addresses (Some architectures use * @clear_lsb: Set to mask off LSB of addresses (Some architectures use
@ -131,8 +132,9 @@ int load_elf_ram_sym(const char *filename,
uint64_t (*elf_note_fn)(void *, void *, bool), uint64_t (*elf_note_fn)(void *, void *, bool),
uint64_t (*translate_fn)(void *, uint64_t), uint64_t (*translate_fn)(void *, uint64_t),
void *translate_opaque, uint64_t *pentry, void *translate_opaque, uint64_t *pentry,
uint64_t *lowaddr, uint64_t *highaddr, int big_endian, uint64_t *lowaddr, uint64_t *highaddr, uint32_t *pflags,
int elf_machine, int clear_lsb, int data_swab, int big_endian, int elf_machine,
int clear_lsb, int data_swab,
AddressSpace *as, bool load_rom, symbol_fn_t sym_cb); AddressSpace *as, bool load_rom, symbol_fn_t sym_cb);
/** load_elf_ram: /** load_elf_ram:
@ -143,9 +145,9 @@ int load_elf_ram(const char *filename,
uint64_t (*elf_note_fn)(void *, void *, bool), uint64_t (*elf_note_fn)(void *, void *, bool),
uint64_t (*translate_fn)(void *, uint64_t), uint64_t (*translate_fn)(void *, uint64_t),
void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr, void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr,
uint64_t *highaddr, int big_endian, int elf_machine, uint64_t *highaddr, uint32_t *pflags, int big_endian,
int clear_lsb, int data_swab, AddressSpace *as, int elf_machine, int clear_lsb, int data_swab,
bool load_rom); AddressSpace *as, bool load_rom);
/** load_elf_as: /** load_elf_as:
* Same as load_elf_ram(), but always loads the elf as ROM * Same as load_elf_ram(), but always loads the elf as ROM
@ -154,8 +156,9 @@ int load_elf_as(const char *filename,
uint64_t (*elf_note_fn)(void *, void *, bool), uint64_t (*elf_note_fn)(void *, void *, bool),
uint64_t (*translate_fn)(void *, uint64_t), uint64_t (*translate_fn)(void *, uint64_t),
void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr, void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr,
uint64_t *highaddr, int big_endian, int elf_machine, uint64_t *highaddr, uint32_t *pflags, int big_endian,
int clear_lsb, int data_swab, AddressSpace *as); int elf_machine, int clear_lsb, int data_swab,
AddressSpace *as);
/** load_elf: /** load_elf:
* Same as load_elf_as(), but doesn't allow the caller to specify an * Same as load_elf_as(), but doesn't allow the caller to specify an
@ -165,8 +168,8 @@ int load_elf(const char *filename,
uint64_t (*elf_note_fn)(void *, void *, bool), uint64_t (*elf_note_fn)(void *, void *, bool),
uint64_t (*translate_fn)(void *, uint64_t), uint64_t (*translate_fn)(void *, uint64_t),
void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr, void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr,
uint64_t *highaddr, int big_endian, int elf_machine, uint64_t *highaddr, uint32_t *pflags, int big_endian,
int clear_lsb, int data_swab); int elf_machine, int clear_lsb, int data_swab);
/** load_elf_hdr: /** load_elf_hdr:
* @filename: Path of ELF file * @filename: Path of ELF file

View File

@ -260,7 +260,7 @@ The 'scsi-disk' device is deprecated. Users should use 'scsi-hd' or
@section System emulator machines @section System emulator machines
@subsection mips r4k platform (since 4.2) @subsection mips r4k platform (since 5.0)
This machine type is very old and unmaintained. Users should use the 'malta' This machine type is very old and unmaintained. Users should use the 'malta'
machine type instead. machine type instead.

View File

@ -309,7 +309,7 @@ typedef struct mips_def_t mips_def_t;
#define CP0_REG04__USERLOCAL 2 #define CP0_REG04__USERLOCAL 2
#define CP0_REG04__XCONTEXTCONFIG 3 #define CP0_REG04__XCONTEXTCONFIG 3
#define CP0_REG04__DBGCONTEXTID 4 #define CP0_REG04__DBGCONTEXTID 4
#define CP0_REG00__MMID 5 #define CP0_REG04__MMID 5
/* CP0 Register 05 */ /* CP0 Register 05 */
#define CP0_REG05__PAGEMASK 0 #define CP0_REG05__PAGEMASK 0
#define CP0_REG05__PAGEGRAIN 1 #define CP0_REG05__PAGEGRAIN 1
@ -961,7 +961,7 @@ struct CPUMIPSState {
/* /*
* CP0 Register 19 * CP0 Register 19
*/ */
int32_t CP0_WatchHi[8]; uint64_t CP0_WatchHi[8];
#define CP0WH_ASID 16 #define CP0WH_ASID 16
/* /*
* CP0 Register 20 * CP0 Register 20

View File

@ -72,8 +72,13 @@ int r4k_map_address(CPUMIPSState *env, hwaddr *physical, int *prot,
target_ulong address, int rw, int access_type) target_ulong address, int rw, int access_type)
{ {
uint16_t ASID = env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask; uint16_t ASID = env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask;
uint32_t MMID = env->CP0_MemoryMapID;
bool mi = !!((env->CP0_Config5 >> CP0C5_MI) & 1);
uint32_t tlb_mmid;
int i; int i;
MMID = mi ? MMID : (uint32_t) ASID;
for (i = 0; i < env->tlb->tlb_in_use; i++) { for (i = 0; i < env->tlb->tlb_in_use; i++) {
r4k_tlb_t *tlb = &env->tlb->mmu.r4k.tlb[i]; r4k_tlb_t *tlb = &env->tlb->mmu.r4k.tlb[i];
/* 1k pages are not supported. */ /* 1k pages are not supported. */
@ -84,8 +89,9 @@ int r4k_map_address(CPUMIPSState *env, hwaddr *physical, int *prot,
tag &= env->SEGMask; tag &= env->SEGMask;
#endif #endif
/* Check ASID, virtual page number & size */ /* Check ASID/MMID, virtual page number & size */
if ((tlb->G == 1 || tlb->ASID == ASID) && VPN == tag && !tlb->EHINV) { tlb_mmid = mi ? tlb->MMID : (uint32_t) tlb->ASID;
if ((tlb->G == 1 || tlb_mmid == MMID) && VPN == tag && !tlb->EHINV) {
/* TLB match */ /* TLB match */
int n = !!(address & mask & ~(mask >> 1)); int n = !!(address & mask & ~(mask >> 1));
/* Check access rights */ /* Check access rights */
@ -1418,14 +1424,20 @@ void r4k_invalidate_tlb(CPUMIPSState *env, int idx, int use_extra)
target_ulong addr; target_ulong addr;
target_ulong end; target_ulong end;
uint16_t ASID = env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask; uint16_t ASID = env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask;
uint32_t MMID = env->CP0_MemoryMapID;
bool mi = !!((env->CP0_Config5 >> CP0C5_MI) & 1);
uint32_t tlb_mmid;
target_ulong mask; target_ulong mask;
MMID = mi ? MMID : (uint32_t) ASID;
tlb = &env->tlb->mmu.r4k.tlb[idx]; tlb = &env->tlb->mmu.r4k.tlb[idx];
/* /*
* The qemu TLB is flushed when the ASID changes, so no need to * The qemu TLB is flushed when the ASID/MMID changes, so no need to
* flush these entries again. * flush these entries again.
*/ */
if (tlb->G == 0 && tlb->ASID != ASID) { tlb_mmid = mi ? tlb->MMID : (uint32_t) tlb->ASID;
if (tlb->G == 0 && tlb_mmid != MMID) {
return; return;
} }

View File

@ -78,6 +78,7 @@ DEF_HELPER_1(mfc0_maar, tl, env)
DEF_HELPER_1(mfhc0_maar, tl, env) DEF_HELPER_1(mfhc0_maar, tl, env)
DEF_HELPER_2(mfc0_watchlo, tl, env, i32) DEF_HELPER_2(mfc0_watchlo, tl, env, i32)
DEF_HELPER_2(mfc0_watchhi, tl, env, i32) DEF_HELPER_2(mfc0_watchhi, tl, env, i32)
DEF_HELPER_2(mfhc0_watchhi, tl, env, i32)
DEF_HELPER_1(mfc0_debug, tl, env) DEF_HELPER_1(mfc0_debug, tl, env)
DEF_HELPER_1(mftc0_debug, tl, env) DEF_HELPER_1(mftc0_debug, tl, env)
#ifdef TARGET_MIPS64 #ifdef TARGET_MIPS64
@ -89,6 +90,7 @@ DEF_HELPER_1(dmfc0_tcschefback, tl, env)
DEF_HELPER_1(dmfc0_lladdr, tl, env) DEF_HELPER_1(dmfc0_lladdr, tl, env)
DEF_HELPER_1(dmfc0_maar, tl, env) DEF_HELPER_1(dmfc0_maar, tl, env)
DEF_HELPER_2(dmfc0_watchlo, tl, env, i32) DEF_HELPER_2(dmfc0_watchlo, tl, env, i32)
DEF_HELPER_2(dmfc0_watchhi, tl, env, i32)
DEF_HELPER_1(dmfc0_saar, tl, env) DEF_HELPER_1(dmfc0_saar, tl, env)
#endif /* TARGET_MIPS64 */ #endif /* TARGET_MIPS64 */
@ -118,6 +120,7 @@ DEF_HELPER_2(mtc0_tcschefback, void, env, tl)
DEF_HELPER_2(mttc0_tcschefback, void, env, tl) DEF_HELPER_2(mttc0_tcschefback, void, env, tl)
DEF_HELPER_2(mtc0_entrylo1, void, env, tl) DEF_HELPER_2(mtc0_entrylo1, void, env, tl)
DEF_HELPER_2(mtc0_context, void, env, tl) DEF_HELPER_2(mtc0_context, void, env, tl)
DEF_HELPER_2(mtc0_memorymapid, void, env, tl)
DEF_HELPER_2(mtc0_pagemask, void, env, tl) DEF_HELPER_2(mtc0_pagemask, void, env, tl)
DEF_HELPER_2(mtc0_pagegrain, void, env, tl) DEF_HELPER_2(mtc0_pagegrain, void, env, tl)
DEF_HELPER_2(mtc0_segctl0, void, env, tl) DEF_HELPER_2(mtc0_segctl0, void, env, tl)
@ -159,6 +162,7 @@ DEF_HELPER_2(mthc0_maar, void, env, tl)
DEF_HELPER_2(mtc0_maari, void, env, tl) DEF_HELPER_2(mtc0_maari, void, env, tl)
DEF_HELPER_3(mtc0_watchlo, void, env, tl, i32) DEF_HELPER_3(mtc0_watchlo, void, env, tl, i32)
DEF_HELPER_3(mtc0_watchhi, void, env, tl, i32) DEF_HELPER_3(mtc0_watchhi, void, env, tl, i32)
DEF_HELPER_3(mthc0_watchhi, void, env, tl, i32)
DEF_HELPER_2(mtc0_xcontext, void, env, tl) DEF_HELPER_2(mtc0_xcontext, void, env, tl)
DEF_HELPER_2(mtc0_framemask, void, env, tl) DEF_HELPER_2(mtc0_framemask, void, env, tl)
DEF_HELPER_2(mtc0_debug, void, env, tl) DEF_HELPER_2(mtc0_debug, void, env, tl)
@ -373,6 +377,7 @@ DEF_HELPER_1(ei, tl, env)
DEF_HELPER_1(eret, void, env) DEF_HELPER_1(eret, void, env)
DEF_HELPER_1(eretnc, void, env) DEF_HELPER_1(eretnc, void, env)
DEF_HELPER_1(deret, void, env) DEF_HELPER_1(deret, void, env)
DEF_HELPER_3(ginvt, void, env, tl, i32)
#endif /* !CONFIG_USER_ONLY */ #endif /* !CONFIG_USER_ONLY */
DEF_HELPER_1(rdhwr_cpunum, tl, env) DEF_HELPER_1(rdhwr_cpunum, tl, env)
DEF_HELPER_1(rdhwr_synci_step, tl, env) DEF_HELPER_1(rdhwr_synci_step, tl, env)

View File

@ -95,6 +95,7 @@ struct r4k_tlb_t {
target_ulong VPN; target_ulong VPN;
uint32_t PageMask; uint32_t PageMask;
uint16_t ASID; uint16_t ASID;
uint32_t MMID;
unsigned int G:1; unsigned int G:1;
unsigned int C0:3; unsigned int C0:3;
unsigned int C1:3; unsigned int C1:3;

View File

@ -212,8 +212,8 @@ const VMStateDescription vmstate_tlb = {
const VMStateDescription vmstate_mips_cpu = { const VMStateDescription vmstate_mips_cpu = {
.name = "cpu", .name = "cpu",
.version_id = 18, .version_id = 19,
.minimum_version_id = 18, .minimum_version_id = 19,
.post_load = cpu_post_load, .post_load = cpu_post_load,
.fields = (VMStateField[]) { .fields = (VMStateField[]) {
/* Active TC */ /* Active TC */
@ -296,7 +296,7 @@ const VMStateDescription vmstate_mips_cpu = {
VMSTATE_INT32(env.CP0_MAARI, MIPSCPU), VMSTATE_INT32(env.CP0_MAARI, MIPSCPU),
VMSTATE_UINTTL(env.lladdr, MIPSCPU), VMSTATE_UINTTL(env.lladdr, MIPSCPU),
VMSTATE_UINTTL_ARRAY(env.CP0_WatchLo, MIPSCPU, 8), VMSTATE_UINTTL_ARRAY(env.CP0_WatchLo, MIPSCPU, 8),
VMSTATE_INT32_ARRAY(env.CP0_WatchHi, MIPSCPU, 8), VMSTATE_UINT64_ARRAY(env.CP0_WatchHi, MIPSCPU, 8),
VMSTATE_UINTTL(env.CP0_XContext, MIPSCPU), VMSTATE_UINTTL(env.CP0_XContext, MIPSCPU),
VMSTATE_INT32(env.CP0_Framemask, MIPSCPU), VMSTATE_INT32(env.CP0_Framemask, MIPSCPU),
VMSTATE_INT32(env.CP0_Debug, MIPSCPU), VMSTATE_INT32(env.CP0_Debug, MIPSCPU),

View File

@ -218,7 +218,7 @@ static int copy_argn_to_target(CPUMIPSState *env, int arg_num,
if (!p) { \ if (!p) { \
gpr[2] = -1; \ gpr[2] = -1; \
gpr[3] = EFAULT; \ gpr[3] = EFAULT; \
goto uhi_done; \ return; \
} \ } \
} while (0) } while (0)
@ -228,14 +228,14 @@ static int copy_argn_to_target(CPUMIPSState *env, int arg_num,
if (!p) { \ if (!p) { \
gpr[2] = -1; \ gpr[2] = -1; \
gpr[3] = EFAULT; \ gpr[3] = EFAULT; \
goto uhi_done; \ return; \
} \ } \
p2 = lock_user_string(addr2); \ p2 = lock_user_string(addr2); \
if (!p2) { \ if (!p2) { \
unlock_user(p, addr, 0); \ unlock_user(p, addr, 0); \
gpr[2] = -1; \ gpr[2] = -1; \
gpr[3] = EFAULT; \ gpr[3] = EFAULT; \
goto uhi_done; \ return; \
} \ } \
} while (0) } while (0)
@ -272,7 +272,7 @@ void helper_do_semihosting(CPUMIPSState *env)
if (gpr[4] < 3) { if (gpr[4] < 3) {
/* ignore closing stdin/stdout/stderr */ /* ignore closing stdin/stdout/stderr */
gpr[2] = 0; gpr[2] = 0;
goto uhi_done; return;
} }
gpr[2] = close(gpr[4]); gpr[2] = close(gpr[4]);
gpr[3] = errno_mips(errno); gpr[3] = errno_mips(errno);
@ -302,7 +302,7 @@ void helper_do_semihosting(CPUMIPSState *env)
gpr[2] = fstat(gpr[4], &sbuf); gpr[2] = fstat(gpr[4], &sbuf);
gpr[3] = errno_mips(errno); gpr[3] = errno_mips(errno);
if (gpr[2]) { if (gpr[2]) {
goto uhi_done; return;
} }
gpr[2] = copy_stat_to_target(env, &sbuf, gpr[5]); gpr[2] = copy_stat_to_target(env, &sbuf, gpr[5]);
gpr[3] = errno_mips(errno); gpr[3] = errno_mips(errno);
@ -314,14 +314,14 @@ void helper_do_semihosting(CPUMIPSState *env)
case UHI_argnlen: case UHI_argnlen:
if (gpr[4] >= semihosting_get_argc()) { if (gpr[4] >= semihosting_get_argc()) {
gpr[2] = -1; gpr[2] = -1;
goto uhi_done; return;
} }
gpr[2] = strlen(semihosting_get_arg(gpr[4])); gpr[2] = strlen(semihosting_get_arg(gpr[4]));
break; break;
case UHI_argn: case UHI_argn:
if (gpr[4] >= semihosting_get_argc()) { if (gpr[4] >= semihosting_get_argc()) {
gpr[2] = -1; gpr[2] = -1;
goto uhi_done; return;
} }
gpr[2] = copy_argn_to_target(env, gpr[4], gpr[5]); gpr[2] = copy_argn_to_target(env, gpr[4], gpr[5]);
break; break;
@ -369,6 +369,5 @@ void helper_do_semihosting(CPUMIPSState *env)
fprintf(stderr, "Unknown UHI operation %d\n", op); fprintf(stderr, "Unknown UHI operation %d\n", op);
abort(); abort();
} }
uhi_done:
return; return;
} }

View File

@ -945,7 +945,12 @@ target_ulong helper_mfc0_watchlo(CPUMIPSState *env, uint32_t sel)
target_ulong helper_mfc0_watchhi(CPUMIPSState *env, uint32_t sel) target_ulong helper_mfc0_watchhi(CPUMIPSState *env, uint32_t sel)
{ {
return env->CP0_WatchHi[sel]; return (int32_t) env->CP0_WatchHi[sel];
}
target_ulong helper_mfhc0_watchhi(CPUMIPSState *env, uint32_t sel)
{
return env->CP0_WatchHi[sel] >> 32;
} }
target_ulong helper_mfc0_debug(CPUMIPSState *env) target_ulong helper_mfc0_debug(CPUMIPSState *env)
@ -1016,6 +1021,11 @@ target_ulong helper_dmfc0_watchlo(CPUMIPSState *env, uint32_t sel)
return env->CP0_WatchLo[sel]; return env->CP0_WatchLo[sel];
} }
target_ulong helper_dmfc0_watchhi(CPUMIPSState *env, uint32_t sel)
{
return env->CP0_WatchHi[sel];
}
target_ulong helper_dmfc0_saar(CPUMIPSState *env) target_ulong helper_dmfc0_saar(CPUMIPSState *env)
{ {
if ((env->CP0_SAARI & 0x3f) < 2) { if ((env->CP0_SAARI & 0x3f) < 2) {
@ -1379,6 +1389,17 @@ void helper_mtc0_context(CPUMIPSState *env, target_ulong arg1)
env->CP0_Context = (env->CP0_Context & 0x007FFFFF) | (arg1 & ~0x007FFFFF); env->CP0_Context = (env->CP0_Context & 0x007FFFFF) | (arg1 & ~0x007FFFFF);
} }
void helper_mtc0_memorymapid(CPUMIPSState *env, target_ulong arg1)
{
int32_t old;
old = env->CP0_MemoryMapID;
env->CP0_MemoryMapID = (int32_t) arg1;
/* If the MemoryMapID changes, flush qemu's TLB. */
if (old != env->CP0_MemoryMapID) {
cpu_mips_tlb_flush(env);
}
}
void update_pagemask(CPUMIPSState *env, target_ulong arg1, int32_t *pagemask) void update_pagemask(CPUMIPSState *env, target_ulong arg1, int32_t *pagemask)
{ {
uint64_t mask = arg1 >> (TARGET_PAGE_BITS + 1); uint64_t mask = arg1 >> (TARGET_PAGE_BITS + 1);
@ -1815,6 +1836,8 @@ void helper_mtc0_config5(CPUMIPSState *env, target_ulong arg1)
{ {
env->CP0_Config5 = (env->CP0_Config5 & (~env->CP0_Config5_rw_bitmask)) | env->CP0_Config5 = (env->CP0_Config5 & (~env->CP0_Config5_rw_bitmask)) |
(arg1 & env->CP0_Config5_rw_bitmask); (arg1 & env->CP0_Config5_rw_bitmask);
env->CP0_EntryHi_ASID_mask = (env->CP0_Config5 & (1 << CP0C5_MI)) ?
0x0 : (env->CP0_Config4 & (1 << CP0C4_AE)) ? 0x3ff : 0xff;
compute_hflags(env); compute_hflags(env);
} }
@ -1869,11 +1892,20 @@ void helper_mtc0_watchlo(CPUMIPSState *env, target_ulong arg1, uint32_t sel)
void helper_mtc0_watchhi(CPUMIPSState *env, target_ulong arg1, uint32_t sel) void helper_mtc0_watchhi(CPUMIPSState *env, target_ulong arg1, uint32_t sel)
{ {
int mask = 0x40000FF8 | (env->CP0_EntryHi_ASID_mask << CP0WH_ASID); uint64_t mask = 0x40000FF8 | (env->CP0_EntryHi_ASID_mask << CP0WH_ASID);
if ((env->CP0_Config5 >> CP0C5_MI) & 1) {
mask |= 0xFFFFFFFF00000000ULL; /* MMID */
}
env->CP0_WatchHi[sel] = arg1 & mask; env->CP0_WatchHi[sel] = arg1 & mask;
env->CP0_WatchHi[sel] &= ~(env->CP0_WatchHi[sel] & arg1 & 0x7); env->CP0_WatchHi[sel] &= ~(env->CP0_WatchHi[sel] & arg1 & 0x7);
} }
void helper_mthc0_watchhi(CPUMIPSState *env, target_ulong arg1, uint32_t sel)
{
env->CP0_WatchHi[sel] = ((uint64_t) (arg1) << 32) |
(env->CP0_WatchHi[sel] & 0x00000000ffffffffULL);
}
void helper_mtc0_xcontext(CPUMIPSState *env, target_ulong arg1) void helper_mtc0_xcontext(CPUMIPSState *env, target_ulong arg1)
{ {
target_ulong mask = (1ULL << (env->SEGBITS - 7)) - 1; target_ulong mask = (1ULL << (env->SEGBITS - 7)) - 1;
@ -2249,6 +2281,7 @@ static void r4k_fill_tlb(CPUMIPSState *env, int idx)
tlb->VPN &= env->SEGMask; tlb->VPN &= env->SEGMask;
#endif #endif
tlb->ASID = env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask; tlb->ASID = env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask;
tlb->MMID = env->CP0_MemoryMapID;
tlb->PageMask = env->CP0_PageMask; tlb->PageMask = env->CP0_PageMask;
tlb->G = env->CP0_EntryLo0 & env->CP0_EntryLo1 & 1; tlb->G = env->CP0_EntryLo0 & env->CP0_EntryLo1 & 1;
tlb->V0 = (env->CP0_EntryLo0 & 2) != 0; tlb->V0 = (env->CP0_EntryLo0 & 2) != 0;
@ -2267,13 +2300,18 @@ static void r4k_fill_tlb(CPUMIPSState *env, int idx)
void r4k_helper_tlbinv(CPUMIPSState *env) void r4k_helper_tlbinv(CPUMIPSState *env)
{ {
int idx; bool mi = !!((env->CP0_Config5 >> CP0C5_MI) & 1);
r4k_tlb_t *tlb;
uint16_t ASID = env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask; uint16_t ASID = env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask;
uint32_t MMID = env->CP0_MemoryMapID;
uint32_t tlb_mmid;
r4k_tlb_t *tlb;
int idx;
MMID = mi ? MMID : (uint32_t) ASID;
for (idx = 0; idx < env->tlb->nb_tlb; idx++) { for (idx = 0; idx < env->tlb->nb_tlb; idx++) {
tlb = &env->tlb->mmu.r4k.tlb[idx]; tlb = &env->tlb->mmu.r4k.tlb[idx];
if (!tlb->G && tlb->ASID == ASID) { tlb_mmid = mi ? tlb->MMID : (uint32_t) tlb->ASID;
if (!tlb->G && tlb_mmid == MMID) {
tlb->EHINV = 1; tlb->EHINV = 1;
} }
} }
@ -2292,11 +2330,16 @@ void r4k_helper_tlbinvf(CPUMIPSState *env)
void r4k_helper_tlbwi(CPUMIPSState *env) void r4k_helper_tlbwi(CPUMIPSState *env)
{ {
bool mi = !!((env->CP0_Config5 >> CP0C5_MI) & 1);
target_ulong VPN;
uint16_t ASID = env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask;
uint32_t MMID = env->CP0_MemoryMapID;
uint32_t tlb_mmid;
bool EHINV, G, V0, D0, V1, D1, XI0, XI1, RI0, RI1;
r4k_tlb_t *tlb; r4k_tlb_t *tlb;
int idx; int idx;
target_ulong VPN;
uint16_t ASID; MMID = mi ? MMID : (uint32_t) ASID;
bool EHINV, G, V0, D0, V1, D1, XI0, XI1, RI0, RI1;
idx = (env->CP0_Index & ~0x80000000) % env->tlb->nb_tlb; idx = (env->CP0_Index & ~0x80000000) % env->tlb->nb_tlb;
tlb = &env->tlb->mmu.r4k.tlb[idx]; tlb = &env->tlb->mmu.r4k.tlb[idx];
@ -2304,7 +2347,6 @@ void r4k_helper_tlbwi(CPUMIPSState *env)
#if defined(TARGET_MIPS64) #if defined(TARGET_MIPS64)
VPN &= env->SEGMask; VPN &= env->SEGMask;
#endif #endif
ASID = env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask;
EHINV = (env->CP0_EntryHi & (1 << CP0EnHi_EHINV)) != 0; EHINV = (env->CP0_EntryHi & (1 << CP0EnHi_EHINV)) != 0;
G = env->CP0_EntryLo0 & env->CP0_EntryLo1 & 1; G = env->CP0_EntryLo0 & env->CP0_EntryLo1 & 1;
V0 = (env->CP0_EntryLo0 & 2) != 0; V0 = (env->CP0_EntryLo0 & 2) != 0;
@ -2316,11 +2358,12 @@ void r4k_helper_tlbwi(CPUMIPSState *env)
XI1 = (env->CP0_EntryLo1 >> CP0EnLo_XI) &1; XI1 = (env->CP0_EntryLo1 >> CP0EnLo_XI) &1;
RI1 = (env->CP0_EntryLo1 >> CP0EnLo_RI) &1; RI1 = (env->CP0_EntryLo1 >> CP0EnLo_RI) &1;
tlb_mmid = mi ? tlb->MMID : (uint32_t) tlb->ASID;
/* /*
* Discard cached TLB entries, unless tlbwi is just upgrading access * Discard cached TLB entries, unless tlbwi is just upgrading access
* permissions on the current entry. * permissions on the current entry.
*/ */
if (tlb->VPN != VPN || tlb->ASID != ASID || tlb->G != G || if (tlb->VPN != VPN || tlb_mmid != MMID || tlb->G != G ||
(!tlb->EHINV && EHINV) || (!tlb->EHINV && EHINV) ||
(tlb->V0 && !V0) || (tlb->D0 && !D0) || (tlb->V0 && !V0) || (tlb->D0 && !D0) ||
(!tlb->XI0 && XI0) || (!tlb->RI0 && RI0) || (!tlb->XI0 && XI0) || (!tlb->RI0 && RI0) ||
@ -2343,14 +2386,17 @@ void r4k_helper_tlbwr(CPUMIPSState *env)
void r4k_helper_tlbp(CPUMIPSState *env) void r4k_helper_tlbp(CPUMIPSState *env)
{ {
bool mi = !!((env->CP0_Config5 >> CP0C5_MI) & 1);
r4k_tlb_t *tlb; r4k_tlb_t *tlb;
target_ulong mask; target_ulong mask;
target_ulong tag; target_ulong tag;
target_ulong VPN; target_ulong VPN;
uint16_t ASID; uint16_t ASID = env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask;
uint32_t MMID = env->CP0_MemoryMapID;
uint32_t tlb_mmid;
int i; int i;
ASID = env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask; MMID = mi ? MMID : (uint32_t) ASID;
for (i = 0; i < env->tlb->nb_tlb; i++) { for (i = 0; i < env->tlb->nb_tlb; i++) {
tlb = &env->tlb->mmu.r4k.tlb[i]; tlb = &env->tlb->mmu.r4k.tlb[i];
/* 1k pages are not supported. */ /* 1k pages are not supported. */
@ -2360,8 +2406,9 @@ void r4k_helper_tlbp(CPUMIPSState *env)
#if defined(TARGET_MIPS64) #if defined(TARGET_MIPS64)
tag &= env->SEGMask; tag &= env->SEGMask;
#endif #endif
/* Check ASID, virtual page number & size */ tlb_mmid = mi ? tlb->MMID : (uint32_t) tlb->ASID;
if ((tlb->G == 1 || tlb->ASID == ASID) && VPN == tag && !tlb->EHINV) { /* Check ASID/MMID, virtual page number & size */
if ((tlb->G == 1 || tlb_mmid == MMID) && VPN == tag && !tlb->EHINV) {
/* TLB match */ /* TLB match */
env->CP0_Index = i; env->CP0_Index = i;
break; break;
@ -2378,8 +2425,9 @@ void r4k_helper_tlbp(CPUMIPSState *env)
#if defined(TARGET_MIPS64) #if defined(TARGET_MIPS64)
tag &= env->SEGMask; tag &= env->SEGMask;
#endif #endif
/* Check ASID, virtual page number & size */ tlb_mmid = mi ? tlb->MMID : (uint32_t) tlb->ASID;
if ((tlb->G == 1 || tlb->ASID == ASID) && VPN == tag) { /* Check ASID/MMID, virtual page number & size */
if ((tlb->G == 1 || tlb_mmid == MMID) && VPN == tag) {
r4k_mips_tlb_flush_extra(env, i); r4k_mips_tlb_flush_extra(env, i);
break; break;
} }
@ -2401,16 +2449,20 @@ static inline uint64_t get_entrylo_pfn_from_tlb(uint64_t tlb_pfn)
void r4k_helper_tlbr(CPUMIPSState *env) void r4k_helper_tlbr(CPUMIPSState *env)
{ {
bool mi = !!((env->CP0_Config5 >> CP0C5_MI) & 1);
uint16_t ASID = env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask;
uint32_t MMID = env->CP0_MemoryMapID;
uint32_t tlb_mmid;
r4k_tlb_t *tlb; r4k_tlb_t *tlb;
uint16_t ASID;
int idx; int idx;
ASID = env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask; MMID = mi ? MMID : (uint32_t) ASID;
idx = (env->CP0_Index & ~0x80000000) % env->tlb->nb_tlb; idx = (env->CP0_Index & ~0x80000000) % env->tlb->nb_tlb;
tlb = &env->tlb->mmu.r4k.tlb[idx]; tlb = &env->tlb->mmu.r4k.tlb[idx];
/* If this will change the current ASID, flush qemu's TLB. */ tlb_mmid = mi ? tlb->MMID : (uint32_t) tlb->ASID;
if (ASID != tlb->ASID) { /* If this will change the current ASID/MMID, flush qemu's TLB. */
if (MMID != tlb_mmid) {
cpu_mips_tlb_flush(env); cpu_mips_tlb_flush(env);
} }
@ -2422,7 +2474,8 @@ void r4k_helper_tlbr(CPUMIPSState *env)
env->CP0_EntryLo0 = 0; env->CP0_EntryLo0 = 0;
env->CP0_EntryLo1 = 0; env->CP0_EntryLo1 = 0;
} else { } else {
env->CP0_EntryHi = tlb->VPN | tlb->ASID; env->CP0_EntryHi = mi ? tlb->VPN : tlb->VPN | tlb->ASID;
env->CP0_MemoryMapID = tlb->MMID;
env->CP0_PageMask = tlb->PageMask; env->CP0_PageMask = tlb->PageMask;
env->CP0_EntryLo0 = tlb->G | (tlb->V0 << 1) | (tlb->D0 << 2) | env->CP0_EntryLo0 = tlb->G | (tlb->V0 << 1) | (tlb->D0 << 2) |
((uint64_t)tlb->RI0 << CP0EnLo_RI) | ((uint64_t)tlb->RI0 << CP0EnLo_RI) |
@ -2465,6 +2518,63 @@ void helper_tlbinvf(CPUMIPSState *env)
env->tlb->helper_tlbinvf(env); env->tlb->helper_tlbinvf(env);
} }
static void global_invalidate_tlb(CPUMIPSState *env,
uint32_t invMsgVPN2,
uint8_t invMsgR,
uint32_t invMsgMMid,
bool invAll,
bool invVAMMid,
bool invMMid,
bool invVA)
{
int idx;
r4k_tlb_t *tlb;
bool VAMatch;
bool MMidMatch;
for (idx = 0; idx < env->tlb->nb_tlb; idx++) {
tlb = &env->tlb->mmu.r4k.tlb[idx];
VAMatch =
(((tlb->VPN & ~tlb->PageMask) == (invMsgVPN2 & ~tlb->PageMask))
#ifdef TARGET_MIPS64
&&
(extract64(env->CP0_EntryHi, 62, 2) == invMsgR)
#endif
);
MMidMatch = tlb->MMID == invMsgMMid;
if ((invAll && (idx > env->CP0_Wired)) ||
(VAMatch && invVAMMid && (tlb->G || MMidMatch)) ||
(VAMatch && invVA) ||
(MMidMatch && !(tlb->G) && invMMid)) {
tlb->EHINV = 1;
}
}
cpu_mips_tlb_flush(env);
}
void helper_ginvt(CPUMIPSState *env, target_ulong arg, uint32_t type)
{
bool invAll = type == 0;
bool invVA = type == 1;
bool invMMid = type == 2;
bool invVAMMid = type == 3;
uint32_t invMsgVPN2 = arg & (TARGET_PAGE_MASK << 1);
uint8_t invMsgR = 0;
uint32_t invMsgMMid = env->CP0_MemoryMapID;
CPUState *other_cs = first_cpu;
#ifdef TARGET_MIPS64
invMsgR = extract64(arg, 62, 2);
#endif
CPU_FOREACH(other_cs) {
MIPSCPU *other_cpu = MIPS_CPU(other_cs);
global_invalidate_tlb(&other_cpu->env, invMsgVPN2, invMsgR, invMsgMMid,
invAll, invVAMMid, invMMid, invVA);
}
}
/* Specials */ /* Specials */
target_ulong helper_di(CPUMIPSState *env) target_ulong helper_di(CPUMIPSState *env)
{ {

View File

@ -388,6 +388,7 @@ enum {
OPC_BSHFL = 0x20 | OPC_SPECIAL3, OPC_BSHFL = 0x20 | OPC_SPECIAL3,
OPC_DBSHFL = 0x24 | OPC_SPECIAL3, OPC_DBSHFL = 0x24 | OPC_SPECIAL3,
OPC_RDHWR = 0x3B | OPC_SPECIAL3, OPC_RDHWR = 0x3B | OPC_SPECIAL3,
OPC_GINV = 0x3D | OPC_SPECIAL3,
/* Loongson 2E */ /* Loongson 2E */
OPC_MULT_G_2E = 0x18 | OPC_SPECIAL3, OPC_MULT_G_2E = 0x18 | OPC_SPECIAL3,
@ -2547,6 +2548,8 @@ typedef struct DisasContext {
bool nan2008; bool nan2008;
bool abs2008; bool abs2008;
bool saar; bool saar;
bool mi;
int gi;
} DisasContext; } DisasContext;
#define DISAS_STOP DISAS_TARGET_0 #define DISAS_STOP DISAS_TARGET_0
@ -6783,6 +6786,25 @@ static void gen_mfhc0(DisasContext *ctx, TCGv arg, int reg, int sel)
goto cp0_unimplemented; goto cp0_unimplemented;
} }
break; break;
case CP0_REGISTER_19:
switch (sel) {
case CP0_REG19__WATCHHI0:
case CP0_REG19__WATCHHI1:
case CP0_REG19__WATCHHI2:
case CP0_REG19__WATCHHI3:
case CP0_REG19__WATCHHI4:
case CP0_REG19__WATCHHI5:
case CP0_REG19__WATCHHI6:
case CP0_REG19__WATCHHI7:
/* upper 32 bits are only available when Config5MI != 0 */
CP0_CHECK(ctx->mi);
gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_WatchHi[sel]), 0);
register_name = "WatchHi";
break;
default:
goto cp0_unimplemented;
}
break;
case CP0_REGISTER_28: case CP0_REGISTER_28:
switch (sel) { switch (sel) {
case 0: case 0:
@ -6869,6 +6891,25 @@ static void gen_mthc0(DisasContext *ctx, TCGv arg, int reg, int sel)
goto cp0_unimplemented; goto cp0_unimplemented;
} }
break; break;
case CP0_REGISTER_19:
switch (sel) {
case CP0_REG19__WATCHHI0:
case CP0_REG19__WATCHHI1:
case CP0_REG19__WATCHHI2:
case CP0_REG19__WATCHHI3:
case CP0_REG19__WATCHHI4:
case CP0_REG19__WATCHHI5:
case CP0_REG19__WATCHHI6:
case CP0_REG19__WATCHHI7:
/* upper 32 bits are only available when Config5MI != 0 */
CP0_CHECK(ctx->mi);
gen_helper_0e1i(mthc0_watchhi, arg, sel);
register_name = "WatchHi";
break;
default:
goto cp0_unimplemented;
}
break;
case CP0_REGISTER_28: case CP0_REGISTER_28:
switch (sel) { switch (sel) {
case 0: case 0:
@ -7092,6 +7133,11 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
tcg_gen_ext32s_tl(arg, arg); tcg_gen_ext32s_tl(arg, arg);
register_name = "UserLocal"; register_name = "UserLocal";
break; break;
case CP0_REG04__MMID:
CP0_CHECK(ctx->mi);
gen_helper_mtc0_memorymapid(cpu_env, arg);
register_name = "MMID";
break;
default: default:
goto cp0_unimplemented; goto cp0_unimplemented;
} }
@ -7832,6 +7878,11 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
offsetof(CPUMIPSState, active_tc.CP0_UserLocal)); offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
register_name = "UserLocal"; register_name = "UserLocal";
break; break;
case CP0_REG04__MMID:
CP0_CHECK(ctx->mi);
gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MemoryMapID));
register_name = "MMID";
break;
default: default:
goto cp0_unimplemented; goto cp0_unimplemented;
} }
@ -8590,6 +8641,11 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
offsetof(CPUMIPSState, active_tc.CP0_UserLocal)); offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
register_name = "UserLocal"; register_name = "UserLocal";
break; break;
case CP0_REG04__MMID:
CP0_CHECK(ctx->mi);
gen_helper_mtc0_memorymapid(cpu_env, arg);
register_name = "MMID";
break;
default: default:
goto cp0_unimplemented; goto cp0_unimplemented;
} }
@ -8922,7 +8978,7 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
case CP0_REG19__WATCHHI6: case CP0_REG19__WATCHHI6:
case CP0_REG19__WATCHHI7: case CP0_REG19__WATCHHI7:
CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR)); CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
gen_helper_1e0i(mfc0_watchhi, arg, sel); gen_helper_1e0i(dmfc0_watchhi, arg, sel);
register_name = "WatchHi"; register_name = "WatchHi";
break; break;
default: default:
@ -9312,6 +9368,11 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
offsetof(CPUMIPSState, active_tc.CP0_UserLocal)); offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
register_name = "UserLocal"; register_name = "UserLocal";
break; break;
case CP0_REG04__MMID:
CP0_CHECK(ctx->mi);
gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MemoryMapID));
register_name = "MMID";
break;
default: default:
goto cp0_unimplemented; goto cp0_unimplemented;
} }
@ -27170,6 +27231,25 @@ static void decode_opc_special3_r6(CPUMIPSState *env, DisasContext *ctx)
} }
} }
break; break;
#ifndef CONFIG_USER_ONLY
case OPC_GINV:
if (unlikely(ctx->gi <= 1)) {
generate_exception_end(ctx, EXCP_RI);
}
check_cp0_enabled(ctx);
switch ((ctx->opcode >> 6) & 3) {
case 0: /* GINVI */
/* Treat as NOP. */
break;
case 2: /* GINVT */
gen_helper_0e1i(ginvt, cpu_gpr[rs], extract32(ctx->opcode, 8, 2));
break;
default:
generate_exception_end(ctx, EXCP_RI);
break;
}
break;
#endif
#if defined(TARGET_MIPS64) #if defined(TARGET_MIPS64)
case R6_OPC_SCD: case R6_OPC_SCD:
gen_st_cond(ctx, rt, rs, imm, MO_TEQ, false); gen_st_cond(ctx, rt, rs, imm, MO_TEQ, false);
@ -30727,6 +30807,8 @@ static void mips_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
ctx->mrp = (env->CP0_Config5 >> CP0C5_MRP) & 1; ctx->mrp = (env->CP0_Config5 >> CP0C5_MRP) & 1;
ctx->nan2008 = (env->active_fpu.fcr31 >> FCR31_NAN2008) & 1; ctx->nan2008 = (env->active_fpu.fcr31 >> FCR31_NAN2008) & 1;
ctx->abs2008 = (env->active_fpu.fcr31 >> FCR31_ABS2008) & 1; ctx->abs2008 = (env->active_fpu.fcr31 >> FCR31_ABS2008) & 1;
ctx->mi = (env->CP0_Config5 >> CP0C5_MI) & 1;
ctx->gi = (env->CP0_Config5 >> CP0C5_GI) & 3;
restore_cpu_state(env, ctx); restore_cpu_state(env, ctx);
#ifdef CONFIG_USER_ONLY #ifdef CONFIG_USER_ONLY
ctx->mem_idx = MIPS_HFLAG_UM; ctx->mem_idx = MIPS_HFLAG_UM;
@ -31187,8 +31269,8 @@ void cpu_state_reset(CPUMIPSState *env)
if (env->CP0_Config3 & (1 << CP0C3_CMGCR)) { if (env->CP0_Config3 & (1 << CP0C3_CMGCR)) {
env->CP0_CMGCRBase = 0x1fbf8000 >> 4; env->CP0_CMGCRBase = 0x1fbf8000 >> 4;
} }
env->CP0_EntryHi_ASID_mask = (env->CP0_Config4 & (1 << CP0C4_AE)) ? env->CP0_EntryHi_ASID_mask = (env->CP0_Config5 & (1 << CP0C5_MI)) ?
0x3ff : 0xff; 0x0 : (env->CP0_Config4 & (1 << CP0C4_AE)) ? 0x3ff : 0xff;
env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL); env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
/* /*
* Vectored interrupts not implemented, timer on int 7, * Vectored interrupts not implemented, timer on int 7,