mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
Merge tag 'pull-target-arm-20230921' of https://git.linaro.org/people/pmaydell/qemu-arm into staging
target-arm queue: * target/m68k: Add URL to semihosting spec * docs/devel/loads-stores: Fix git grep regexes * hw/arm/boot: Set SCR_EL3.FGTEn when booting kernel * linux-user: Correct SME feature names reported in cpuinfo * linux-user: Add missing arm32 hwcaps * Don't skip MTE checks for LDRT/STRT at EL0 * Implement FEAT_HBC * Implement FEAT_MOPS * audio/jackaudio: Avoid dynamic stack allocation * sbsa-ref: add non-secure EL2 virtual timer * elf2dmp: improve Win2022, Win11 and large dumps # -----BEGIN PGP SIGNATURE----- # # iQJNBAABCAA3FiEE4aXFk81BneKOgxXPPCUl7RQ2DN4FAmUMfwAZHHBldGVyLm1h # eWRlbGxAbGluYXJvLm9yZwAKCRA8JSXtFDYM3jvnD/0QE/oOxfr+wkDUkTasSwVc # UNfhObMj3h8x2XApqXckXnckew97I7hh7OLk35p9Ncea7fb6CvGMZ/DJir7AG4aQ # Anpd5g2Qo0AMfPIyvoJ5pgtqZ1aS/EpBfYixmjL/zY6+zNzoVzWG/KfL+XamW6ir # 6U7EqcAUzfX0+Splcxs5WgCDI5nGtn0B42EwOMpmwsH4opfr6HTn8Rzbn9gIwKU7 # u82PaKAqWPYD0ev9NQra+VVTrrFS4SCcqkV+SoYu0Cg5vvBlgAVcx0Zz2objp9LC # 96fOtFH4Rch611j87WiGvN+fxQawqYzAYdy2y+j0wwuonTH9G3PpdZZT0557NjeS # rFpW2UQebDqZ3ZTDwhzefsVKc3emLZtEd+RFa/YcDtao0afKfbSHv5A2/pGHxzlv # 8psKOOH82WXTOHwFKA2o0lXDAauzirY+1Avy0vozNzPCdErXPgMHY4tABU77PpER # Pz17jJO9C1AGyQVF+o09ieJR2Du5Wb2LLcZP3+5Ctm0SNVmREKKNcMkhJiEM9snm # PQBR7FNEbAuQAO2MDK70dWUcTNtOv4Q1jgTR+aYd2MrArxCmAA5Zd9gjeYDwv6XH # n242ONDAhlG1fY5f5giE3vCrcV1FDbvHEn6GDVilgMrF3a3Iw30xUaATiO09hIfi # XAwGwLtMsp21WDa5PsfZVw== # =dalQ # -----END PGP SIGNATURE----- # gpg: Signature made Thu 21 Sep 2023 13:36:00 EDT # gpg: using RSA key E1A5C593CD419DE28E8315CF3C2525ED14360CDE # gpg: issuer "peter.maydell@linaro.org" # gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>" [full] # gpg: aka "Peter Maydell <pmaydell@gmail.com>" [full] # gpg: aka "Peter Maydell <pmaydell@chiark.greenend.org.uk>" [full] # gpg: aka "Peter Maydell <peter@archaic.org.uk>" [unknown] # Primary key fingerprint: E1A5 C593 CD41 9DE2 8E83 15CF 3C25 25ED 1436 0CDE * tag 'pull-target-arm-20230921' of https://git.linaro.org/people/pmaydell/qemu-arm: (30 commits) elf2dmp: rework PDB_STREAM_INDEXES::segments obtaining elf2dmp: use Linux mmap with MAP_NORESERVE when possible elf2dmp: introduce merging of physical memory runs elf2dmp: introduce physical block alignment elf2dmp: replace PE export name check with PDB name check sbsa-ref: add non-secure EL2 virtual timer audio/jackaudio: Avoid dynamic stack allocation in qjack_process() audio/jackaudio: Avoid dynamic stack allocation in qjack_client_init target/arm: Enable FEAT_MOPS for CPU 'max' target/arm: Implement the CPY* instructions target/arm: Implement MTE tag-checking functions for FEAT_MOPS copies target/arm: Implement the SETG* instructions target/arm: Define new TB flag for ATA0 target/arm: Implement the SET* instructions target/arm: Implement MTE tag-checking functions for FEAT_MOPS target/arm: New function allocation_tag_mem_probe() target/arm: Define syndrome function for MOPS exceptions target/arm: Pass unpriv bool to get_a64_user_mem_index() target/arm: Implement FEAT_MOPS enable bits target/arm: Don't skip MTE checks for LDRT/STRT at EL0 ... Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
+14
-7
@@ -70,6 +70,9 @@ typedef struct QJackClient {
|
||||
int buffersize;
|
||||
jack_port_t **port;
|
||||
QJackBuffer fifo;
|
||||
|
||||
/* Used as workspace by qjack_process() */
|
||||
float **process_buffers;
|
||||
}
|
||||
QJackClient;
|
||||
|
||||
@@ -267,22 +270,21 @@ static int qjack_process(jack_nframes_t nframes, void *arg)
|
||||
}
|
||||
|
||||
/* get the buffers for the ports */
|
||||
float *buffers[c->nchannels];
|
||||
for (int i = 0; i < c->nchannels; ++i) {
|
||||
buffers[i] = jack_port_get_buffer(c->port[i], nframes);
|
||||
c->process_buffers[i] = jack_port_get_buffer(c->port[i], nframes);
|
||||
}
|
||||
|
||||
if (c->out) {
|
||||
if (likely(c->enabled)) {
|
||||
qjack_buffer_read_l(&c->fifo, buffers, nframes);
|
||||
qjack_buffer_read_l(&c->fifo, c->process_buffers, nframes);
|
||||
} else {
|
||||
for (int i = 0; i < c->nchannels; ++i) {
|
||||
memset(buffers[i], 0, nframes * sizeof(float));
|
||||
memset(c->process_buffers[i], 0, nframes * sizeof(float));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (likely(c->enabled)) {
|
||||
qjack_buffer_write_l(&c->fifo, buffers, nframes);
|
||||
qjack_buffer_write_l(&c->fifo, c->process_buffers, nframes);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -400,7 +402,8 @@ static void qjack_client_connect_ports(QJackClient *c)
|
||||
static int qjack_client_init(QJackClient *c)
|
||||
{
|
||||
jack_status_t status;
|
||||
char client_name[jack_client_name_size()];
|
||||
int client_name_len = jack_client_name_size(); /* includes NUL */
|
||||
g_autofree char *client_name = g_new(char, client_name_len);
|
||||
jack_options_t options = JackNullOption;
|
||||
|
||||
if (c->state == QJACK_STATE_RUNNING) {
|
||||
@@ -409,7 +412,7 @@ static int qjack_client_init(QJackClient *c)
|
||||
|
||||
c->connect_ports = true;
|
||||
|
||||
snprintf(client_name, sizeof(client_name), "%s-%s",
|
||||
snprintf(client_name, client_name_len, "%s-%s",
|
||||
c->out ? "out" : "in",
|
||||
c->opt->client_name ? c->opt->client_name : audio_application_name());
|
||||
|
||||
@@ -447,6 +450,9 @@ static int qjack_client_init(QJackClient *c)
|
||||
jack_get_client_name(c->client));
|
||||
}
|
||||
|
||||
/* Allocate working buffer for process callback */
|
||||
c->process_buffers = g_new(float *, c->nchannels);
|
||||
|
||||
jack_set_process_callback(c->client, qjack_process , c);
|
||||
jack_set_port_registration_callback(c->client, qjack_port_registration, c);
|
||||
jack_set_xrun_callback(c->client, qjack_xrun, c);
|
||||
@@ -578,6 +584,7 @@ static void qjack_client_fini_locked(QJackClient *c)
|
||||
|
||||
qjack_buffer_free(&c->fifo);
|
||||
g_free(c->port);
|
||||
g_free(c->process_buffers);
|
||||
|
||||
c->state = QJACK_STATE_DISCONNECTED;
|
||||
/* fallthrough */
|
||||
|
||||
@@ -14,7 +14,7 @@ static struct pa_block *pa_space_find_block(struct pa_space *ps, uint64_t pa)
|
||||
|
||||
for (i = 0; i < ps->block_nr; i++) {
|
||||
if (ps->block[i].paddr <= pa &&
|
||||
pa <= ps->block[i].paddr + ps->block[i].size) {
|
||||
pa < ps->block[i].paddr + ps->block[i].size) {
|
||||
return ps->block + i;
|
||||
}
|
||||
}
|
||||
@@ -33,6 +33,30 @@ static uint8_t *pa_space_resolve(struct pa_space *ps, uint64_t pa)
|
||||
return block->addr + (pa - block->paddr);
|
||||
}
|
||||
|
||||
static void pa_block_align(struct pa_block *b)
|
||||
{
|
||||
uint64_t low_align = ((b->paddr - 1) | ELF2DMP_PAGE_MASK) + 1 - b->paddr;
|
||||
uint64_t high_align = (b->paddr + b->size) & ELF2DMP_PAGE_MASK;
|
||||
|
||||
if (low_align == 0 && high_align == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (low_align + high_align < b->size) {
|
||||
printf("Block 0x%"PRIx64"+:0x%"PRIx64" will be aligned to "
|
||||
"0x%"PRIx64"+:0x%"PRIx64"\n", b->paddr, b->size,
|
||||
b->paddr + low_align, b->size - low_align - high_align);
|
||||
b->size -= low_align + high_align;
|
||||
} else {
|
||||
printf("Block 0x%"PRIx64"+:0x%"PRIx64" is too small to align\n",
|
||||
b->paddr, b->size);
|
||||
b->size = 0;
|
||||
}
|
||||
|
||||
b->addr += low_align;
|
||||
b->paddr += low_align;
|
||||
}
|
||||
|
||||
int pa_space_create(struct pa_space *ps, QEMU_Elf *qemu_elf)
|
||||
{
|
||||
Elf64_Half phdr_nr = elf_getphdrnum(qemu_elf->map);
|
||||
@@ -60,10 +84,13 @@ int pa_space_create(struct pa_space *ps, QEMU_Elf *qemu_elf)
|
||||
.paddr = phdr[i].p_paddr,
|
||||
.size = phdr[i].p_filesz,
|
||||
};
|
||||
block_i++;
|
||||
pa_block_align(&ps->block[block_i]);
|
||||
block_i = ps->block[block_i].size ? (block_i + 1) : block_i;
|
||||
}
|
||||
}
|
||||
|
||||
ps->block_nr = block_i;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
|
||||
#define ELF2DMP_PAGE_BITS 12
|
||||
#define ELF2DMP_PAGE_SIZE (1ULL << ELF2DMP_PAGE_BITS)
|
||||
#define ELF2DMP_PAGE_MASK (ELF2DMP_PAGE_SIZE - 1)
|
||||
#define ELF2DMP_PFN_MASK (~(ELF2DMP_PAGE_SIZE - 1))
|
||||
|
||||
#define INVALID_PA UINT64_MAX
|
||||
|
||||
+84
-70
@@ -20,6 +20,7 @@
|
||||
#define PE_NAME "ntoskrnl.exe"
|
||||
|
||||
#define INITIAL_MXCSR 0x1f80
|
||||
#define MAX_NUMBER_OF_RUNS 42
|
||||
|
||||
typedef struct idt_desc {
|
||||
uint16_t offset1; /* offset bits 0..15 */
|
||||
@@ -234,6 +235,42 @@ static int fix_dtb(struct va_space *vs, QEMU_Elf *qe)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void try_merge_runs(struct pa_space *ps,
|
||||
WinDumpPhyMemDesc64 *PhysicalMemoryBlock)
|
||||
{
|
||||
unsigned int merge_cnt = 0, run_idx = 0;
|
||||
|
||||
PhysicalMemoryBlock->NumberOfRuns = 0;
|
||||
|
||||
for (size_t idx = 0; idx < ps->block_nr; idx++) {
|
||||
struct pa_block *blk = ps->block + idx;
|
||||
struct pa_block *next = blk + 1;
|
||||
|
||||
PhysicalMemoryBlock->NumberOfPages += blk->size / ELF2DMP_PAGE_SIZE;
|
||||
|
||||
if (idx + 1 != ps->block_nr && blk->paddr + blk->size == next->paddr) {
|
||||
printf("Block #%zu 0x%"PRIx64"+:0x%"PRIx64" and %u previous will be"
|
||||
" merged\n", idx, blk->paddr, blk->size, merge_cnt);
|
||||
merge_cnt++;
|
||||
} else {
|
||||
struct pa_block *first_merged = blk - merge_cnt;
|
||||
|
||||
printf("Block #%zu 0x%"PRIx64"+:0x%"PRIx64" and %u previous will be"
|
||||
" merged to 0x%"PRIx64"+:0x%"PRIx64" (run #%u)\n",
|
||||
idx, blk->paddr, blk->size, merge_cnt, first_merged->paddr,
|
||||
blk->paddr + blk->size - first_merged->paddr, run_idx);
|
||||
PhysicalMemoryBlock->Run[run_idx] = (WinDumpPhyMemRun64) {
|
||||
.BasePage = first_merged->paddr / ELF2DMP_PAGE_SIZE,
|
||||
.PageCount = (blk->paddr + blk->size - first_merged->paddr) /
|
||||
ELF2DMP_PAGE_SIZE,
|
||||
};
|
||||
PhysicalMemoryBlock->NumberOfRuns++;
|
||||
run_idx++;
|
||||
merge_cnt = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int fill_header(WinDumpHeader64 *hdr, struct pa_space *ps,
|
||||
struct va_space *vs, uint64_t KdDebuggerDataBlock,
|
||||
KDDEBUGGER_DATA64 *kdbg, uint64_t KdVersionBlock, int nr_cpus)
|
||||
@@ -244,7 +281,6 @@ static int fill_header(WinDumpHeader64 *hdr, struct pa_space *ps,
|
||||
KUSD_OFFSET_PRODUCT_TYPE);
|
||||
DBGKD_GET_VERSION64 kvb;
|
||||
WinDumpHeader64 h;
|
||||
size_t i;
|
||||
|
||||
QEMU_BUILD_BUG_ON(KUSD_OFFSET_SUITE_MASK >= ELF2DMP_PAGE_SIZE);
|
||||
QEMU_BUILD_BUG_ON(KUSD_OFFSET_PRODUCT_TYPE >= ELF2DMP_PAGE_SIZE);
|
||||
@@ -282,13 +318,17 @@ static int fill_header(WinDumpHeader64 *hdr, struct pa_space *ps,
|
||||
.RequiredDumpSpace = sizeof(h),
|
||||
};
|
||||
|
||||
for (i = 0; i < ps->block_nr; i++) {
|
||||
h.PhysicalMemoryBlock.NumberOfPages +=
|
||||
ps->block[i].size / ELF2DMP_PAGE_SIZE;
|
||||
h.PhysicalMemoryBlock.Run[i] = (WinDumpPhyMemRun64) {
|
||||
.BasePage = ps->block[i].paddr / ELF2DMP_PAGE_SIZE,
|
||||
.PageCount = ps->block[i].size / ELF2DMP_PAGE_SIZE,
|
||||
};
|
||||
if (h.PhysicalMemoryBlock.NumberOfRuns <= MAX_NUMBER_OF_RUNS) {
|
||||
for (size_t idx = 0; idx < ps->block_nr; idx++) {
|
||||
h.PhysicalMemoryBlock.NumberOfPages +=
|
||||
ps->block[idx].size / ELF2DMP_PAGE_SIZE;
|
||||
h.PhysicalMemoryBlock.Run[idx] = (WinDumpPhyMemRun64) {
|
||||
.BasePage = ps->block[idx].paddr / ELF2DMP_PAGE_SIZE,
|
||||
.PageCount = ps->block[idx].size / ELF2DMP_PAGE_SIZE,
|
||||
};
|
||||
}
|
||||
} else {
|
||||
try_merge_runs(ps, &h.PhysicalMemoryBlock);
|
||||
}
|
||||
|
||||
h.RequiredDumpSpace +=
|
||||
@@ -400,9 +440,10 @@ static int write_dump(struct pa_space *ps,
|
||||
for (i = 0; i < ps->block_nr; i++) {
|
||||
struct pa_block *b = &ps->block[i];
|
||||
|
||||
printf("Writing block #%zu/%zu to file...\n", i, ps->block_nr);
|
||||
printf("Writing block #%zu/%zu of %"PRIu64" bytes to file...\n", i,
|
||||
ps->block_nr, b->size);
|
||||
if (fwrite(b->addr, b->size, 1, dmp_file) != 1) {
|
||||
eprintf("Failed to write dump header\n");
|
||||
eprintf("Failed to write block\n");
|
||||
fclose(dmp_file);
|
||||
return 1;
|
||||
}
|
||||
@@ -411,89 +452,64 @@ static int write_dump(struct pa_space *ps,
|
||||
return fclose(dmp_file);
|
||||
}
|
||||
|
||||
static bool pe_check_export_name(uint64_t base, void *start_addr,
|
||||
struct va_space *vs)
|
||||
{
|
||||
IMAGE_EXPORT_DIRECTORY export_dir;
|
||||
const char *pe_name;
|
||||
|
||||
if (pe_get_data_dir_entry(base, start_addr, IMAGE_FILE_EXPORT_DIRECTORY,
|
||||
&export_dir, sizeof(export_dir), vs)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
pe_name = va_space_resolve(vs, base + export_dir.Name);
|
||||
if (!pe_name) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return !strcmp(pe_name, PE_NAME);
|
||||
}
|
||||
|
||||
static int pe_get_pdb_symstore_hash(uint64_t base, void *start_addr,
|
||||
char *hash, struct va_space *vs)
|
||||
static bool pe_check_pdb_name(uint64_t base, void *start_addr,
|
||||
struct va_space *vs, OMFSignatureRSDS *rsds)
|
||||
{
|
||||
const char sign_rsds[4] = "RSDS";
|
||||
IMAGE_DEBUG_DIRECTORY debug_dir;
|
||||
OMFSignatureRSDS rsds;
|
||||
char *pdb_name;
|
||||
size_t pdb_name_sz;
|
||||
size_t i;
|
||||
char pdb_name[sizeof(PDB_NAME)];
|
||||
|
||||
if (pe_get_data_dir_entry(base, start_addr, IMAGE_FILE_DEBUG_DIRECTORY,
|
||||
&debug_dir, sizeof(debug_dir), vs)) {
|
||||
eprintf("Failed to get Debug Directory\n");
|
||||
return 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (debug_dir.Type != IMAGE_DEBUG_TYPE_CODEVIEW) {
|
||||
return 1;
|
||||
eprintf("Debug Directory type is not CodeView\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (va_space_rw(vs,
|
||||
base + debug_dir.AddressOfRawData,
|
||||
&rsds, sizeof(rsds), 0)) {
|
||||
return 1;
|
||||
rsds, sizeof(*rsds), 0)) {
|
||||
eprintf("Failed to resolve OMFSignatureRSDS\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
printf("CodeView signature is \'%.4s\'\n", rsds.Signature);
|
||||
|
||||
if (memcmp(&rsds.Signature, sign_rsds, sizeof(sign_rsds))) {
|
||||
return 1;
|
||||
if (memcmp(&rsds->Signature, sign_rsds, sizeof(sign_rsds))) {
|
||||
eprintf("CodeView signature is \'%.4s\', \'%s\' expected\n",
|
||||
rsds->Signature, sign_rsds);
|
||||
return false;
|
||||
}
|
||||
|
||||
pdb_name_sz = debug_dir.SizeOfData - sizeof(rsds);
|
||||
pdb_name = malloc(pdb_name_sz);
|
||||
if (!pdb_name) {
|
||||
return 1;
|
||||
if (debug_dir.SizeOfData - sizeof(*rsds) != sizeof(PDB_NAME)) {
|
||||
eprintf("PDB name size doesn't match\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (va_space_rw(vs, base + debug_dir.AddressOfRawData +
|
||||
offsetof(OMFSignatureRSDS, name), pdb_name, pdb_name_sz, 0)) {
|
||||
free(pdb_name);
|
||||
return 1;
|
||||
offsetof(OMFSignatureRSDS, name), pdb_name, sizeof(PDB_NAME),
|
||||
0)) {
|
||||
eprintf("Failed to resolve PDB name\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
printf("PDB name is \'%s\', \'%s\' expected\n", pdb_name, PDB_NAME);
|
||||
|
||||
if (strcmp(pdb_name, PDB_NAME)) {
|
||||
eprintf("Unexpected PDB name, it seems the kernel isn't found\n");
|
||||
free(pdb_name);
|
||||
return 1;
|
||||
}
|
||||
return !strcmp(pdb_name, PDB_NAME);
|
||||
}
|
||||
|
||||
free(pdb_name);
|
||||
|
||||
sprintf(hash, "%.08x%.04x%.04x%.02x%.02x", rsds.guid.a, rsds.guid.b,
|
||||
rsds.guid.c, rsds.guid.d[0], rsds.guid.d[1]);
|
||||
static void pe_get_pdb_symstore_hash(OMFSignatureRSDS *rsds, char *hash)
|
||||
{
|
||||
sprintf(hash, "%.08x%.04x%.04x%.02x%.02x", rsds->guid.a, rsds->guid.b,
|
||||
rsds->guid.c, rsds->guid.d[0], rsds->guid.d[1]);
|
||||
hash += 20;
|
||||
for (i = 0; i < 6; i++, hash += 2) {
|
||||
sprintf(hash, "%.02x", rsds.guid.e[i]);
|
||||
for (unsigned int i = 0; i < 6; i++, hash += 2) {
|
||||
sprintf(hash, "%.02x", rsds->guid.e[i]);
|
||||
}
|
||||
|
||||
sprintf(hash, "%.01x", rsds.age);
|
||||
|
||||
return 0;
|
||||
sprintf(hash, "%.01x", rsds->age);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
@@ -515,6 +531,7 @@ int main(int argc, char *argv[])
|
||||
KDDEBUGGER_DATA64 *kdbg;
|
||||
uint64_t KdVersionBlock;
|
||||
bool kernel_found = false;
|
||||
OMFSignatureRSDS rsds;
|
||||
|
||||
if (argc != 3) {
|
||||
eprintf("usage:\n\t%s elf_file dmp_file\n", argv[0]);
|
||||
@@ -562,7 +579,8 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
if (*(uint16_t *)nt_start_addr == 0x5a4d) { /* MZ */
|
||||
if (pe_check_export_name(KernBase, nt_start_addr, &vs)) {
|
||||
printf("Checking candidate KernBase = 0x%016"PRIx64"\n", KernBase);
|
||||
if (pe_check_pdb_name(KernBase, nt_start_addr, &vs, &rsds)) {
|
||||
kernel_found = true;
|
||||
break;
|
||||
}
|
||||
@@ -578,11 +596,7 @@ int main(int argc, char *argv[])
|
||||
printf("KernBase = 0x%016"PRIx64", signature is \'%.2s\'\n", KernBase,
|
||||
(char *)nt_start_addr);
|
||||
|
||||
if (pe_get_pdb_symstore_hash(KernBase, nt_start_addr, pdb_hash, &vs)) {
|
||||
eprintf("Failed to get PDB symbol store hash\n");
|
||||
err = 1;
|
||||
goto out_ps;
|
||||
}
|
||||
pe_get_pdb_symstore_hash(&rsds, pdb_hash);
|
||||
|
||||
sprintf(pdb_url, "%s%s/%s/%s", SYM_URL_BASE, PDB_NAME, pdb_hash, PDB_NAME);
|
||||
printf("PDB URL is %s\n", pdb_url);
|
||||
|
||||
+4
-11
@@ -160,7 +160,7 @@ static void *pdb_ds_read_file(struct pdb_reader* r, uint32_t file_number)
|
||||
static int pdb_init_segments(struct pdb_reader *r)
|
||||
{
|
||||
char *segs;
|
||||
unsigned stream_idx = r->sidx.segments;
|
||||
unsigned stream_idx = r->segments;
|
||||
|
||||
segs = pdb_ds_read_file(r, stream_idx);
|
||||
if (!segs) {
|
||||
@@ -177,9 +177,6 @@ static int pdb_init_symbols(struct pdb_reader *r)
|
||||
{
|
||||
int err = 0;
|
||||
PDB_SYMBOLS *symbols;
|
||||
PDB_STREAM_INDEXES *sidx = &r->sidx;
|
||||
|
||||
memset(sidx, -1, sizeof(*sidx));
|
||||
|
||||
symbols = pdb_ds_read_file(r, 3);
|
||||
if (!symbols) {
|
||||
@@ -188,15 +185,11 @@ static int pdb_init_symbols(struct pdb_reader *r)
|
||||
|
||||
r->symbols = symbols;
|
||||
|
||||
if (symbols->stream_index_size != sizeof(PDB_STREAM_INDEXES)) {
|
||||
err = 1;
|
||||
goto out_symbols;
|
||||
}
|
||||
|
||||
memcpy(sidx, (const char *)symbols + sizeof(PDB_SYMBOLS) +
|
||||
r->segments = *(uint16_t *)((const char *)symbols + sizeof(PDB_SYMBOLS) +
|
||||
symbols->module_size + symbols->offset_size +
|
||||
symbols->hash_size + symbols->srcmodule_size +
|
||||
symbols->pdbimport_size + symbols->unknown2_size, sizeof(*sidx));
|
||||
symbols->pdbimport_size + symbols->unknown2_size +
|
||||
offsetof(PDB_STREAM_INDEXES, segments));
|
||||
|
||||
/* Read global symbol table */
|
||||
r->modimage = pdb_ds_read_file(r, symbols->gsym_file);
|
||||
|
||||
@@ -227,7 +227,7 @@ struct pdb_reader {
|
||||
} ds;
|
||||
uint32_t file_used[1024];
|
||||
PDB_SYMBOLS *symbols;
|
||||
PDB_STREAM_INDEXES sidx;
|
||||
uint16_t segments;
|
||||
uint8_t *modimage;
|
||||
char *segs;
|
||||
size_t segs_size;
|
||||
|
||||
+56
-12
@@ -165,10 +165,40 @@ static bool check_ehdr(QEMU_Elf *qe)
|
||||
return true;
|
||||
}
|
||||
|
||||
int QEMU_Elf_init(QEMU_Elf *qe, const char *filename)
|
||||
static int QEMU_Elf_map(QEMU_Elf *qe, const char *filename)
|
||||
{
|
||||
#ifdef CONFIG_LINUX
|
||||
struct stat st;
|
||||
int fd;
|
||||
|
||||
printf("Using Linux mmap\n");
|
||||
|
||||
fd = open(filename, O_RDONLY, 0);
|
||||
if (fd == -1) {
|
||||
eprintf("Failed to open ELF dump file \'%s\'\n", filename);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (fstat(fd, &st)) {
|
||||
eprintf("Failed to get size of ELF dump file\n");
|
||||
close(fd);
|
||||
return 1;
|
||||
}
|
||||
qe->size = st.st_size;
|
||||
|
||||
qe->map = mmap(NULL, qe->size, PROT_READ | PROT_WRITE,
|
||||
MAP_PRIVATE | MAP_NORESERVE, fd, 0);
|
||||
if (qe->map == MAP_FAILED) {
|
||||
eprintf("Failed to map ELF file\n");
|
||||
close(fd);
|
||||
return 1;
|
||||
}
|
||||
|
||||
close(fd);
|
||||
#else
|
||||
GError *gerr = NULL;
|
||||
int err = 0;
|
||||
|
||||
printf("Using GLib mmap\n");
|
||||
|
||||
qe->gmf = g_mapped_file_new(filename, TRUE, &gerr);
|
||||
if (gerr) {
|
||||
@@ -179,29 +209,43 @@ int QEMU_Elf_init(QEMU_Elf *qe, const char *filename)
|
||||
|
||||
qe->map = g_mapped_file_get_contents(qe->gmf);
|
||||
qe->size = g_mapped_file_get_length(qe->gmf);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void QEMU_Elf_unmap(QEMU_Elf *qe)
|
||||
{
|
||||
#ifdef CONFIG_LINUX
|
||||
munmap(qe->map, qe->size);
|
||||
#else
|
||||
g_mapped_file_unref(qe->gmf);
|
||||
#endif
|
||||
}
|
||||
|
||||
int QEMU_Elf_init(QEMU_Elf *qe, const char *filename)
|
||||
{
|
||||
if (QEMU_Elf_map(qe, filename)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!check_ehdr(qe)) {
|
||||
eprintf("Input file has the wrong format\n");
|
||||
err = 1;
|
||||
goto out_unmap;
|
||||
QEMU_Elf_unmap(qe);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (init_states(qe)) {
|
||||
eprintf("Failed to extract QEMU CPU states\n");
|
||||
err = 1;
|
||||
goto out_unmap;
|
||||
QEMU_Elf_unmap(qe);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
out_unmap:
|
||||
g_mapped_file_unref(qe->gmf);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
void QEMU_Elf_exit(QEMU_Elf *qe)
|
||||
{
|
||||
exit_states(qe);
|
||||
g_mapped_file_unref(qe->gmf);
|
||||
QEMU_Elf_unmap(qe);
|
||||
}
|
||||
|
||||
@@ -32,7 +32,9 @@ typedef struct QEMUCPUState {
|
||||
int is_system(QEMUCPUState *s);
|
||||
|
||||
typedef struct QEMU_Elf {
|
||||
#ifndef CONFIG_LINUX
|
||||
GMappedFile *gmf;
|
||||
#endif
|
||||
size_t size;
|
||||
void *map;
|
||||
QEMUCPUState **state;
|
||||
|
||||
+20
-20
@@ -63,12 +63,12 @@ which stores ``val`` to ``ptr`` as an ``{endian}`` order value
|
||||
of size ``sz`` bytes.
|
||||
|
||||
|
||||
Regexes for git grep
|
||||
Regexes for git grep:
|
||||
- ``\<ld[us]\?[bwlq]\(_[hbl]e\)\?_p\>``
|
||||
- ``\<st[bwlq]\(_[hbl]e\)\?_p\>``
|
||||
- ``\<st24\(_[hbl]e\)\?_p\>``
|
||||
- ``\<ldn_\([hbl]e\)?_p\>``
|
||||
- ``\<stn_\([hbl]e\)?_p\>``
|
||||
- ``\<ldn_\([hbl]e\)\?_p\>``
|
||||
- ``\<stn_\([hbl]e\)\?_p\>``
|
||||
|
||||
``cpu_{ld,st}*_mmu``
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
@@ -121,8 +121,8 @@ store: ``cpu_st{size}{end}_mmu(env, ptr, val, oi, retaddr)``
|
||||
- ``_le`` : little endian
|
||||
|
||||
Regexes for git grep:
|
||||
- ``\<cpu_ld[bwlq](_[bl]e)\?_mmu\>``
|
||||
- ``\<cpu_st[bwlq](_[bl]e)\?_mmu\>``
|
||||
- ``\<cpu_ld[bwlq]\(_[bl]e\)\?_mmu\>``
|
||||
- ``\<cpu_st[bwlq]\(_[bl]e\)\?_mmu\>``
|
||||
|
||||
|
||||
``cpu_{ld,st}*_mmuidx_ra``
|
||||
@@ -155,8 +155,8 @@ store: ``cpu_st{size}{end}_mmuidx_ra(env, ptr, val, mmuidx, retaddr)``
|
||||
- ``_le`` : little endian
|
||||
|
||||
Regexes for git grep:
|
||||
- ``\<cpu_ld[us]\?[bwlq](_[bl]e)\?_mmuidx_ra\>``
|
||||
- ``\<cpu_st[bwlq](_[bl]e)\?_mmuidx_ra\>``
|
||||
- ``\<cpu_ld[us]\?[bwlq]\(_[bl]e\)\?_mmuidx_ra\>``
|
||||
- ``\<cpu_st[bwlq]\(_[bl]e\)\?_mmuidx_ra\>``
|
||||
|
||||
``cpu_{ld,st}*_data_ra``
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
@@ -193,8 +193,8 @@ store: ``cpu_st{size}{end}_data_ra(env, ptr, val, ra)``
|
||||
- ``_le`` : little endian
|
||||
|
||||
Regexes for git grep:
|
||||
- ``\<cpu_ld[us]\?[bwlq](_[bl]e)\?_data_ra\>``
|
||||
- ``\<cpu_st[bwlq](_[bl]e)\?_data_ra\>``
|
||||
- ``\<cpu_ld[us]\?[bwlq]\(_[bl]e\)\?_data_ra\>``
|
||||
- ``\<cpu_st[bwlq]\(_[bl]e\)\?_data_ra\>``
|
||||
|
||||
``cpu_{ld,st}*_data``
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
@@ -231,9 +231,9 @@ store: ``cpu_st{size}{end}_data(env, ptr, val)``
|
||||
- ``_be`` : big endian
|
||||
- ``_le`` : little endian
|
||||
|
||||
Regexes for git grep
|
||||
- ``\<cpu_ld[us]\?[bwlq](_[bl]e)\?_data\>``
|
||||
- ``\<cpu_st[bwlq](_[bl]e)\?_data\+\>``
|
||||
Regexes for git grep:
|
||||
- ``\<cpu_ld[us]\?[bwlq]\(_[bl]e\)\?_data\>``
|
||||
- ``\<cpu_st[bwlq]\(_[bl]e\)\?_data\+\>``
|
||||
|
||||
``cpu_ld*_code``
|
||||
~~~~~~~~~~~~~~~~
|
||||
@@ -296,7 +296,7 @@ swap: ``translator_ld{sign}{size}_swap(env, ptr, swap)``
|
||||
- ``l`` : 32 bits
|
||||
- ``q`` : 64 bits
|
||||
|
||||
Regexes for git grep
|
||||
Regexes for git grep:
|
||||
- ``\<translator_ld[us]\?[bwlq]\(_swap\)\?\>``
|
||||
|
||||
``helper_{ld,st}*_mmu``
|
||||
@@ -325,7 +325,7 @@ store: ``helper_{size}_mmu(env, addr, val, opindex, retaddr)``
|
||||
- ``l`` : 32 bits
|
||||
- ``q`` : 64 bits
|
||||
|
||||
Regexes for git grep
|
||||
Regexes for git grep:
|
||||
- ``\<helper_ld[us]\?[bwlq]_mmu\>``
|
||||
- ``\<helper_st[bwlq]_mmu\>``
|
||||
|
||||
@@ -382,7 +382,7 @@ succeeded using a MemTxResult return code.
|
||||
|
||||
The ``_{endian}`` suffix is omitted for byte accesses.
|
||||
|
||||
Regexes for git grep
|
||||
Regexes for git grep:
|
||||
- ``\<address_space_\(read\|write\|rw\)\>``
|
||||
- ``\<address_space_ldu\?[bwql]\(_[lb]e\)\?\>``
|
||||
- ``\<address_space_st[bwql]\(_[lb]e\)\?\>``
|
||||
@@ -400,7 +400,7 @@ Note that portions of the write which attempt to write data to a
|
||||
device will be silently ignored -- only real RAM and ROM will
|
||||
be written to.
|
||||
|
||||
Regexes for git grep
|
||||
Regexes for git grep:
|
||||
- ``address_space_write_rom``
|
||||
|
||||
``{ld,st}*_phys``
|
||||
@@ -438,7 +438,7 @@ device doing the access has no way to report such an error.
|
||||
|
||||
The ``_{endian}_`` infix is omitted for byte accesses.
|
||||
|
||||
Regexes for git grep
|
||||
Regexes for git grep:
|
||||
- ``\<ldu\?[bwlq]\(_[bl]e\)\?_phys\>``
|
||||
- ``\<st[bwlq]\(_[bl]e\)\?_phys\>``
|
||||
|
||||
@@ -462,7 +462,7 @@ For new code they are better avoided:
|
||||
|
||||
``cpu_physical_memory_rw``
|
||||
|
||||
Regexes for git grep
|
||||
Regexes for git grep:
|
||||
- ``\<cpu_physical_memory_\(read\|write\|rw\)\>``
|
||||
|
||||
``cpu_memory_rw_debug``
|
||||
@@ -497,7 +497,7 @@ make sure our existing code is doing things correctly.
|
||||
|
||||
``dma_memory_rw``
|
||||
|
||||
Regexes for git grep
|
||||
Regexes for git grep:
|
||||
- ``\<dma_memory_\(read\|write\|rw\)\>``
|
||||
- ``\<ldu\?[bwlq]\(_[bl]e\)\?_dma\>``
|
||||
- ``\<st[bwlq]\(_[bl]e\)\?_dma\>``
|
||||
@@ -538,7 +538,7 @@ correct address space for that device.
|
||||
|
||||
The ``_{endian}_`` infix is omitted for byte accesses.
|
||||
|
||||
Regexes for git grep
|
||||
Regexes for git grep:
|
||||
- ``\<pci_dma_\(read\|write\|rw\)\>``
|
||||
- ``\<ldu\?[bwlq]\(_[bl]e\)\?_pci_dma\>``
|
||||
- ``\<st[bwlq]\(_[bl]e\)\?_pci_dma\>``
|
||||
|
||||
@@ -42,6 +42,7 @@ the following architecture extensions:
|
||||
- FEAT_FlagM2 (Enhancements to flag manipulation instructions)
|
||||
- FEAT_GTG (Guest translation granule size)
|
||||
- FEAT_HAFDBS (Hardware management of the access flag and dirty bit state)
|
||||
- FEAT_HBC (Hinted conditional branches)
|
||||
- FEAT_HCX (Support for the HCRX_EL2 register)
|
||||
- FEAT_HPDS (Hierarchical permission disables)
|
||||
- FEAT_HPDS2 (Translation table page-based hardware attributes)
|
||||
@@ -57,6 +58,7 @@ the following architecture extensions:
|
||||
- FEAT_LSE (Large System Extensions)
|
||||
- FEAT_LSE2 (Large System Extensions v2)
|
||||
- FEAT_LVA (Large Virtual Address space)
|
||||
- FEAT_MOPS (Standardization of memory operations)
|
||||
- FEAT_MTE (Memory Tagging Extension)
|
||||
- FEAT_MTE2 (Memory Tagging Extension)
|
||||
- FEAT_MTE3 (MTE Asymmetric Fault Handling)
|
||||
|
||||
@@ -761,6 +761,10 @@ static void do_cpu_reset(void *opaque)
|
||||
if (cpu_isar_feature(aa64_hcx, cpu)) {
|
||||
env->cp15.scr_el3 |= SCR_HXEN;
|
||||
}
|
||||
if (cpu_isar_feature(aa64_fgt, cpu)) {
|
||||
env->cp15.scr_el3 |= SCR_FGTEN;
|
||||
}
|
||||
|
||||
/* AArch64 kernels never boot in secure mode */
|
||||
assert(!info->secure_boot);
|
||||
/* This hook is only supported for AArch32 currently:
|
||||
|
||||
@@ -61,6 +61,7 @@
|
||||
#define ARCH_TIMER_S_EL1_IRQ 13
|
||||
#define ARCH_TIMER_NS_EL1_IRQ 14
|
||||
#define ARCH_TIMER_NS_EL2_IRQ 10
|
||||
#define ARCH_TIMER_NS_EL2_VIRT_IRQ 12
|
||||
|
||||
enum {
|
||||
SBSA_FLASH,
|
||||
@@ -489,6 +490,7 @@ static void create_gic(SBSAMachineState *sms, MemoryRegion *mem)
|
||||
[GTIMER_VIRT] = ARCH_TIMER_VIRT_IRQ,
|
||||
[GTIMER_HYP] = ARCH_TIMER_NS_EL2_IRQ,
|
||||
[GTIMER_SEC] = ARCH_TIMER_S_EL1_IRQ,
|
||||
[GTIMER_HYPVIRT] = ARCH_TIMER_NS_EL2_VIRT_IRQ,
|
||||
};
|
||||
|
||||
for (irq = 0; irq < ARRAY_SIZE(timer_irq); irq++) {
|
||||
|
||||
+65
-7
@@ -402,6 +402,12 @@ enum
|
||||
ARM_HWCAP_ARM_VFPD32 = 1 << 19,
|
||||
ARM_HWCAP_ARM_LPAE = 1 << 20,
|
||||
ARM_HWCAP_ARM_EVTSTRM = 1 << 21,
|
||||
ARM_HWCAP_ARM_FPHP = 1 << 22,
|
||||
ARM_HWCAP_ARM_ASIMDHP = 1 << 23,
|
||||
ARM_HWCAP_ARM_ASIMDDP = 1 << 24,
|
||||
ARM_HWCAP_ARM_ASIMDFHM = 1 << 25,
|
||||
ARM_HWCAP_ARM_ASIMDBF16 = 1 << 26,
|
||||
ARM_HWCAP_ARM_I8MM = 1 << 27,
|
||||
};
|
||||
|
||||
enum {
|
||||
@@ -410,6 +416,8 @@ enum {
|
||||
ARM_HWCAP2_ARM_SHA1 = 1 << 2,
|
||||
ARM_HWCAP2_ARM_SHA2 = 1 << 3,
|
||||
ARM_HWCAP2_ARM_CRC32 = 1 << 4,
|
||||
ARM_HWCAP2_ARM_SB = 1 << 5,
|
||||
ARM_HWCAP2_ARM_SSBS = 1 << 6,
|
||||
};
|
||||
|
||||
/* The commpage only exists for 32 bit kernels */
|
||||
@@ -498,6 +506,16 @@ uint32_t get_elf_hwcap(void)
|
||||
}
|
||||
}
|
||||
GET_FEATURE_ID(aa32_simdfmac, ARM_HWCAP_ARM_VFPv4);
|
||||
/*
|
||||
* MVFR1.FPHP and .SIMDHP must be in sync, and QEMU uses the same
|
||||
* isar_feature function for both. The kernel reports them as two hwcaps.
|
||||
*/
|
||||
GET_FEATURE_ID(aa32_fp16_arith, ARM_HWCAP_ARM_FPHP);
|
||||
GET_FEATURE_ID(aa32_fp16_arith, ARM_HWCAP_ARM_ASIMDHP);
|
||||
GET_FEATURE_ID(aa32_dp, ARM_HWCAP_ARM_ASIMDDP);
|
||||
GET_FEATURE_ID(aa32_fhm, ARM_HWCAP_ARM_ASIMDFHM);
|
||||
GET_FEATURE_ID(aa32_bf16, ARM_HWCAP_ARM_ASIMDBF16);
|
||||
GET_FEATURE_ID(aa32_i8mm, ARM_HWCAP_ARM_I8MM);
|
||||
|
||||
return hwcaps;
|
||||
}
|
||||
@@ -512,6 +530,8 @@ uint32_t get_elf_hwcap2(void)
|
||||
GET_FEATURE_ID(aa32_sha1, ARM_HWCAP2_ARM_SHA1);
|
||||
GET_FEATURE_ID(aa32_sha2, ARM_HWCAP2_ARM_SHA2);
|
||||
GET_FEATURE_ID(aa32_crc32, ARM_HWCAP2_ARM_CRC32);
|
||||
GET_FEATURE_ID(aa32_sb, ARM_HWCAP2_ARM_SB);
|
||||
GET_FEATURE_ID(aa32_ssbs, ARM_HWCAP2_ARM_SSBS);
|
||||
return hwcaps;
|
||||
}
|
||||
|
||||
@@ -540,6 +560,12 @@ const char *elf_hwcap_str(uint32_t bit)
|
||||
[__builtin_ctz(ARM_HWCAP_ARM_VFPD32 )] = "vfpd32",
|
||||
[__builtin_ctz(ARM_HWCAP_ARM_LPAE )] = "lpae",
|
||||
[__builtin_ctz(ARM_HWCAP_ARM_EVTSTRM )] = "evtstrm",
|
||||
[__builtin_ctz(ARM_HWCAP_ARM_FPHP )] = "fphp",
|
||||
[__builtin_ctz(ARM_HWCAP_ARM_ASIMDHP )] = "asimdhp",
|
||||
[__builtin_ctz(ARM_HWCAP_ARM_ASIMDDP )] = "asimddp",
|
||||
[__builtin_ctz(ARM_HWCAP_ARM_ASIMDFHM )] = "asimdfhm",
|
||||
[__builtin_ctz(ARM_HWCAP_ARM_ASIMDBF16)] = "asimdbf16",
|
||||
[__builtin_ctz(ARM_HWCAP_ARM_I8MM )] = "i8mm",
|
||||
};
|
||||
|
||||
return bit < ARRAY_SIZE(hwcap_str) ? hwcap_str[bit] : NULL;
|
||||
@@ -553,6 +579,8 @@ const char *elf_hwcap2_str(uint32_t bit)
|
||||
[__builtin_ctz(ARM_HWCAP2_ARM_SHA1 )] = "sha1",
|
||||
[__builtin_ctz(ARM_HWCAP2_ARM_SHA2 )] = "sha2",
|
||||
[__builtin_ctz(ARM_HWCAP2_ARM_CRC32)] = "crc32",
|
||||
[__builtin_ctz(ARM_HWCAP2_ARM_SB )] = "sb",
|
||||
[__builtin_ctz(ARM_HWCAP2_ARM_SSBS )] = "ssbs",
|
||||
};
|
||||
|
||||
return bit < ARRAY_SIZE(hwcap_str) ? hwcap_str[bit] : NULL;
|
||||
@@ -696,6 +724,20 @@ enum {
|
||||
ARM_HWCAP2_A64_SME_B16F32 = 1 << 28,
|
||||
ARM_HWCAP2_A64_SME_F32F32 = 1 << 29,
|
||||
ARM_HWCAP2_A64_SME_FA64 = 1 << 30,
|
||||
ARM_HWCAP2_A64_WFXT = 1ULL << 31,
|
||||
ARM_HWCAP2_A64_EBF16 = 1ULL << 32,
|
||||
ARM_HWCAP2_A64_SVE_EBF16 = 1ULL << 33,
|
||||
ARM_HWCAP2_A64_CSSC = 1ULL << 34,
|
||||
ARM_HWCAP2_A64_RPRFM = 1ULL << 35,
|
||||
ARM_HWCAP2_A64_SVE2P1 = 1ULL << 36,
|
||||
ARM_HWCAP2_A64_SME2 = 1ULL << 37,
|
||||
ARM_HWCAP2_A64_SME2P1 = 1ULL << 38,
|
||||
ARM_HWCAP2_A64_SME_I16I32 = 1ULL << 39,
|
||||
ARM_HWCAP2_A64_SME_BI32I32 = 1ULL << 40,
|
||||
ARM_HWCAP2_A64_SME_B16B16 = 1ULL << 41,
|
||||
ARM_HWCAP2_A64_SME_F16F16 = 1ULL << 42,
|
||||
ARM_HWCAP2_A64_MOPS = 1ULL << 43,
|
||||
ARM_HWCAP2_A64_HBC = 1ULL << 44,
|
||||
};
|
||||
|
||||
#define ELF_HWCAP get_elf_hwcap()
|
||||
@@ -773,6 +815,8 @@ uint32_t get_elf_hwcap2(void)
|
||||
GET_FEATURE_ID(aa64_sme_f64f64, ARM_HWCAP2_A64_SME_F64F64);
|
||||
GET_FEATURE_ID(aa64_sme_i16i64, ARM_HWCAP2_A64_SME_I16I64);
|
||||
GET_FEATURE_ID(aa64_sme_fa64, ARM_HWCAP2_A64_SME_FA64);
|
||||
GET_FEATURE_ID(aa64_hbc, ARM_HWCAP2_A64_HBC);
|
||||
GET_FEATURE_ID(aa64_mops, ARM_HWCAP2_A64_MOPS);
|
||||
|
||||
return hwcaps;
|
||||
}
|
||||
@@ -844,13 +888,27 @@ const char *elf_hwcap2_str(uint32_t bit)
|
||||
[__builtin_ctz(ARM_HWCAP2_A64_RPRES )] = "rpres",
|
||||
[__builtin_ctz(ARM_HWCAP2_A64_MTE3 )] = "mte3",
|
||||
[__builtin_ctz(ARM_HWCAP2_A64_SME )] = "sme",
|
||||
[__builtin_ctz(ARM_HWCAP2_A64_SME_I16I64 )] = "sme_i16i64",
|
||||
[__builtin_ctz(ARM_HWCAP2_A64_SME_F64F64 )] = "sme_f64f64",
|
||||
[__builtin_ctz(ARM_HWCAP2_A64_SME_I8I32 )] = "sme_i8i32",
|
||||
[__builtin_ctz(ARM_HWCAP2_A64_SME_F16F32 )] = "sme_f16f32",
|
||||
[__builtin_ctz(ARM_HWCAP2_A64_SME_B16F32 )] = "sme_b16f32",
|
||||
[__builtin_ctz(ARM_HWCAP2_A64_SME_F32F32 )] = "sme_f32f32",
|
||||
[__builtin_ctz(ARM_HWCAP2_A64_SME_FA64 )] = "sme_fa64",
|
||||
[__builtin_ctz(ARM_HWCAP2_A64_SME_I16I64 )] = "smei16i64",
|
||||
[__builtin_ctz(ARM_HWCAP2_A64_SME_F64F64 )] = "smef64f64",
|
||||
[__builtin_ctz(ARM_HWCAP2_A64_SME_I8I32 )] = "smei8i32",
|
||||
[__builtin_ctz(ARM_HWCAP2_A64_SME_F16F32 )] = "smef16f32",
|
||||
[__builtin_ctz(ARM_HWCAP2_A64_SME_B16F32 )] = "smeb16f32",
|
||||
[__builtin_ctz(ARM_HWCAP2_A64_SME_F32F32 )] = "smef32f32",
|
||||
[__builtin_ctz(ARM_HWCAP2_A64_SME_FA64 )] = "smefa64",
|
||||
[__builtin_ctz(ARM_HWCAP2_A64_WFXT )] = "wfxt",
|
||||
[__builtin_ctzll(ARM_HWCAP2_A64_EBF16 )] = "ebf16",
|
||||
[__builtin_ctzll(ARM_HWCAP2_A64_SVE_EBF16 )] = "sveebf16",
|
||||
[__builtin_ctzll(ARM_HWCAP2_A64_CSSC )] = "cssc",
|
||||
[__builtin_ctzll(ARM_HWCAP2_A64_RPRFM )] = "rprfm",
|
||||
[__builtin_ctzll(ARM_HWCAP2_A64_SVE2P1 )] = "sve2p1",
|
||||
[__builtin_ctzll(ARM_HWCAP2_A64_SME2 )] = "sme2",
|
||||
[__builtin_ctzll(ARM_HWCAP2_A64_SME2P1 )] = "sme2p1",
|
||||
[__builtin_ctzll(ARM_HWCAP2_A64_SME_I16I32 )] = "smei16i32",
|
||||
[__builtin_ctzll(ARM_HWCAP2_A64_SME_BI32I32)] = "smebi32i32",
|
||||
[__builtin_ctzll(ARM_HWCAP2_A64_SME_B16B16 )] = "smeb16b16",
|
||||
[__builtin_ctzll(ARM_HWCAP2_A64_SME_F16F16 )] = "smef16f16",
|
||||
[__builtin_ctzll(ARM_HWCAP2_A64_MOPS )] = "mops",
|
||||
[__builtin_ctzll(ARM_HWCAP2_A64_HBC )] = "hbc",
|
||||
};
|
||||
|
||||
return bit < ARRAY_SIZE(hwcap_str) ? hwcap_str[bit] : NULL;
|
||||
|
||||
@@ -1315,6 +1315,7 @@ void pmu_init(ARMCPU *cpu);
|
||||
#define SCTLR_EnIB (1U << 30) /* v8.3, AArch64 only */
|
||||
#define SCTLR_EnIA (1U << 31) /* v8.3, AArch64 only */
|
||||
#define SCTLR_DSSBS_32 (1U << 31) /* v8.5, AArch32 only */
|
||||
#define SCTLR_MSCEN (1ULL << 33) /* FEAT_MOPS */
|
||||
#define SCTLR_BT0 (1ULL << 35) /* v8.5-BTI */
|
||||
#define SCTLR_BT1 (1ULL << 36) /* v8.5-BTI */
|
||||
#define SCTLR_ITFSB (1ULL << 37) /* v8.5-MemTag */
|
||||
@@ -2166,6 +2167,7 @@ FIELD(ID_AA64ISAR0, SHA1, 8, 4)
|
||||
FIELD(ID_AA64ISAR0, SHA2, 12, 4)
|
||||
FIELD(ID_AA64ISAR0, CRC32, 16, 4)
|
||||
FIELD(ID_AA64ISAR0, ATOMIC, 20, 4)
|
||||
FIELD(ID_AA64ISAR0, TME, 24, 4)
|
||||
FIELD(ID_AA64ISAR0, RDM, 28, 4)
|
||||
FIELD(ID_AA64ISAR0, SHA3, 32, 4)
|
||||
FIELD(ID_AA64ISAR0, SM3, 36, 4)
|
||||
@@ -2200,6 +2202,13 @@ FIELD(ID_AA64ISAR2, APA3, 12, 4)
|
||||
FIELD(ID_AA64ISAR2, MOPS, 16, 4)
|
||||
FIELD(ID_AA64ISAR2, BC, 20, 4)
|
||||
FIELD(ID_AA64ISAR2, PAC_FRAC, 24, 4)
|
||||
FIELD(ID_AA64ISAR2, CLRBHB, 28, 4)
|
||||
FIELD(ID_AA64ISAR2, SYSREG_128, 32, 4)
|
||||
FIELD(ID_AA64ISAR2, SYSINSTR_128, 36, 4)
|
||||
FIELD(ID_AA64ISAR2, PRFMSLC, 40, 4)
|
||||
FIELD(ID_AA64ISAR2, RPRFM, 48, 4)
|
||||
FIELD(ID_AA64ISAR2, CSSC, 52, 4)
|
||||
FIELD(ID_AA64ISAR2, ATS1A, 60, 4)
|
||||
|
||||
FIELD(ID_AA64PFR0, EL0, 0, 4)
|
||||
FIELD(ID_AA64PFR0, EL1, 4, 4)
|
||||
@@ -2227,6 +2236,12 @@ FIELD(ID_AA64PFR1, SME, 24, 4)
|
||||
FIELD(ID_AA64PFR1, RNDR_TRAP, 28, 4)
|
||||
FIELD(ID_AA64PFR1, CSV2_FRAC, 32, 4)
|
||||
FIELD(ID_AA64PFR1, NMI, 36, 4)
|
||||
FIELD(ID_AA64PFR1, MTE_FRAC, 40, 4)
|
||||
FIELD(ID_AA64PFR1, GCS, 44, 4)
|
||||
FIELD(ID_AA64PFR1, THE, 48, 4)
|
||||
FIELD(ID_AA64PFR1, MTEX, 52, 4)
|
||||
FIELD(ID_AA64PFR1, DF2, 56, 4)
|
||||
FIELD(ID_AA64PFR1, PFAR, 60, 4)
|
||||
|
||||
FIELD(ID_AA64MMFR0, PARANGE, 0, 4)
|
||||
FIELD(ID_AA64MMFR0, ASIDBITS, 4, 4)
|
||||
@@ -2258,6 +2273,7 @@ FIELD(ID_AA64MMFR1, AFP, 44, 4)
|
||||
FIELD(ID_AA64MMFR1, NTLBPA, 48, 4)
|
||||
FIELD(ID_AA64MMFR1, TIDCP1, 52, 4)
|
||||
FIELD(ID_AA64MMFR1, CMOW, 56, 4)
|
||||
FIELD(ID_AA64MMFR1, ECBHB, 60, 4)
|
||||
|
||||
FIELD(ID_AA64MMFR2, CNP, 0, 4)
|
||||
FIELD(ID_AA64MMFR2, UAO, 4, 4)
|
||||
@@ -2279,7 +2295,9 @@ FIELD(ID_AA64DFR0, DEBUGVER, 0, 4)
|
||||
FIELD(ID_AA64DFR0, TRACEVER, 4, 4)
|
||||
FIELD(ID_AA64DFR0, PMUVER, 8, 4)
|
||||
FIELD(ID_AA64DFR0, BRPS, 12, 4)
|
||||
FIELD(ID_AA64DFR0, PMSS, 16, 4)
|
||||
FIELD(ID_AA64DFR0, WRPS, 20, 4)
|
||||
FIELD(ID_AA64DFR0, SEBEP, 24, 4)
|
||||
FIELD(ID_AA64DFR0, CTX_CMPS, 28, 4)
|
||||
FIELD(ID_AA64DFR0, PMSVER, 32, 4)
|
||||
FIELD(ID_AA64DFR0, DOUBLELOCK, 36, 4)
|
||||
@@ -2287,12 +2305,14 @@ FIELD(ID_AA64DFR0, TRACEFILT, 40, 4)
|
||||
FIELD(ID_AA64DFR0, TRACEBUFFER, 44, 4)
|
||||
FIELD(ID_AA64DFR0, MTPMU, 48, 4)
|
||||
FIELD(ID_AA64DFR0, BRBE, 52, 4)
|
||||
FIELD(ID_AA64DFR0, EXTTRCBUFF, 56, 4)
|
||||
FIELD(ID_AA64DFR0, HPMN0, 60, 4)
|
||||
|
||||
FIELD(ID_AA64ZFR0, SVEVER, 0, 4)
|
||||
FIELD(ID_AA64ZFR0, AES, 4, 4)
|
||||
FIELD(ID_AA64ZFR0, BITPERM, 16, 4)
|
||||
FIELD(ID_AA64ZFR0, BFLOAT16, 20, 4)
|
||||
FIELD(ID_AA64ZFR0, B16B16, 24, 4)
|
||||
FIELD(ID_AA64ZFR0, SHA3, 32, 4)
|
||||
FIELD(ID_AA64ZFR0, SM4, 40, 4)
|
||||
FIELD(ID_AA64ZFR0, I8MM, 44, 4)
|
||||
@@ -2300,9 +2320,13 @@ FIELD(ID_AA64ZFR0, F32MM, 52, 4)
|
||||
FIELD(ID_AA64ZFR0, F64MM, 56, 4)
|
||||
|
||||
FIELD(ID_AA64SMFR0, F32F32, 32, 1)
|
||||
FIELD(ID_AA64SMFR0, BI32I32, 33, 1)
|
||||
FIELD(ID_AA64SMFR0, B16F32, 34, 1)
|
||||
FIELD(ID_AA64SMFR0, F16F32, 35, 1)
|
||||
FIELD(ID_AA64SMFR0, I8I32, 36, 4)
|
||||
FIELD(ID_AA64SMFR0, F16F16, 42, 1)
|
||||
FIELD(ID_AA64SMFR0, B16B16, 43, 1)
|
||||
FIELD(ID_AA64SMFR0, I16I32, 44, 4)
|
||||
FIELD(ID_AA64SMFR0, F64F64, 48, 1)
|
||||
FIELD(ID_AA64SMFR0, I16I64, 52, 4)
|
||||
FIELD(ID_AA64SMFR0, SMEVER, 56, 4)
|
||||
@@ -3147,6 +3171,7 @@ FIELD(TBFLAG_A64, SVL, 24, 4)
|
||||
FIELD(TBFLAG_A64, SME_TRAP_NONSTREAMING, 28, 1)
|
||||
FIELD(TBFLAG_A64, FGT_ERET, 29, 1)
|
||||
FIELD(TBFLAG_A64, NAA, 30, 1)
|
||||
FIELD(TBFLAG_A64, ATA0, 31, 1)
|
||||
|
||||
/*
|
||||
* Helpers for using the above.
|
||||
@@ -4065,6 +4090,11 @@ static inline bool isar_feature_aa64_i8mm(const ARMISARegisters *id)
|
||||
return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, I8MM) != 0;
|
||||
}
|
||||
|
||||
static inline bool isar_feature_aa64_hbc(const ARMISARegisters *id)
|
||||
{
|
||||
return FIELD_EX64(id->id_aa64isar2, ID_AA64ISAR2, BC) != 0;
|
||||
}
|
||||
|
||||
static inline bool isar_feature_aa64_tgran4_lpa2(const ARMISARegisters *id)
|
||||
{
|
||||
return FIELD_SEX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN4) >= 1;
|
||||
@@ -4253,6 +4283,11 @@ static inline bool isar_feature_aa64_doublelock(const ARMISARegisters *id)
|
||||
return FIELD_SEX64(id->id_aa64dfr0, ID_AA64DFR0, DOUBLELOCK) >= 0;
|
||||
}
|
||||
|
||||
static inline bool isar_feature_aa64_mops(const ARMISARegisters *id)
|
||||
{
|
||||
return FIELD_EX64(id->id_aa64isar2, ID_AA64ISAR2, MOPS);
|
||||
}
|
||||
|
||||
/*
|
||||
* Feature tests for "does this exist in either 32-bit or 64-bit?"
|
||||
*/
|
||||
|
||||
+31
-8
@@ -5980,7 +5980,10 @@ static void hcrx_write(CPUARMState *env, const ARMCPRegInfo *ri,
|
||||
{
|
||||
uint64_t valid_mask = 0;
|
||||
|
||||
/* No features adding bits to HCRX are implemented. */
|
||||
/* FEAT_MOPS adds MSCEn and MCE2 */
|
||||
if (cpu_isar_feature(aa64_mops, env_archcpu(env))) {
|
||||
valid_mask |= HCRX_MSCEN | HCRX_MCE2;
|
||||
}
|
||||
|
||||
/* Clear RES0 bits. */
|
||||
env->cp15.hcrx_el2 = value & valid_mask;
|
||||
@@ -6009,13 +6012,24 @@ uint64_t arm_hcrx_el2_eff(CPUARMState *env)
|
||||
{
|
||||
/*
|
||||
* The bits in this register behave as 0 for all purposes other than
|
||||
* direct reads of the register if:
|
||||
* - EL2 is not enabled in the current security state,
|
||||
* - SCR_EL3.HXEn is 0.
|
||||
* direct reads of the register if SCR_EL3.HXEn is 0.
|
||||
* If EL2 is not enabled in the current security state, then the
|
||||
* bit may behave as if 0, or as if 1, depending on the bit.
|
||||
* For the moment, we treat the EL2-disabled case as taking
|
||||
* priority over the HXEn-disabled case. This is true for the only
|
||||
* bit for a feature which we implement where the answer is different
|
||||
* for the two cases (MSCEn for FEAT_MOPS).
|
||||
* This may need to be revisited for future bits.
|
||||
*/
|
||||
if (!arm_is_el2_enabled(env)
|
||||
|| (arm_feature(env, ARM_FEATURE_EL3)
|
||||
&& !(env->cp15.scr_el3 & SCR_HXEN))) {
|
||||
if (!arm_is_el2_enabled(env)) {
|
||||
uint64_t hcrx = 0;
|
||||
if (cpu_isar_feature(aa64_mops, env_archcpu(env))) {
|
||||
/* MSCEn behaves as 1 if EL2 is not enabled */
|
||||
hcrx |= HCRX_MSCEN;
|
||||
}
|
||||
return hcrx;
|
||||
}
|
||||
if (arm_feature(env, ARM_FEATURE_EL3) && !(env->cp15.scr_el3 & SCR_HXEN)) {
|
||||
return 0;
|
||||
}
|
||||
return env->cp15.hcrx_el2;
|
||||
@@ -8621,11 +8635,16 @@ void register_cp_regs_for_features(ARMCPU *cpu)
|
||||
R_ID_AA64ZFR0_F64MM_MASK },
|
||||
{ .name = "ID_AA64SMFR0_EL1",
|
||||
.exported_bits = R_ID_AA64SMFR0_F32F32_MASK |
|
||||
R_ID_AA64SMFR0_BI32I32_MASK |
|
||||
R_ID_AA64SMFR0_B16F32_MASK |
|
||||
R_ID_AA64SMFR0_F16F32_MASK |
|
||||
R_ID_AA64SMFR0_I8I32_MASK |
|
||||
R_ID_AA64SMFR0_F16F16_MASK |
|
||||
R_ID_AA64SMFR0_B16B16_MASK |
|
||||
R_ID_AA64SMFR0_I16I32_MASK |
|
||||
R_ID_AA64SMFR0_F64F64_MASK |
|
||||
R_ID_AA64SMFR0_I16I64_MASK |
|
||||
R_ID_AA64SMFR0_SMEVER_MASK |
|
||||
R_ID_AA64SMFR0_FA64_MASK },
|
||||
{ .name = "ID_AA64MMFR0_EL1",
|
||||
.exported_bits = R_ID_AA64MMFR0_ECV_MASK,
|
||||
@@ -8676,7 +8695,11 @@ void register_cp_regs_for_features(ARMCPU *cpu)
|
||||
.exported_bits = R_ID_AA64ISAR2_WFXT_MASK |
|
||||
R_ID_AA64ISAR2_RPRES_MASK |
|
||||
R_ID_AA64ISAR2_GPA3_MASK |
|
||||
R_ID_AA64ISAR2_APA3_MASK },
|
||||
R_ID_AA64ISAR2_APA3_MASK |
|
||||
R_ID_AA64ISAR2_MOPS_MASK |
|
||||
R_ID_AA64ISAR2_BC_MASK |
|
||||
R_ID_AA64ISAR2_RPRFM_MASK |
|
||||
R_ID_AA64ISAR2_CSSC_MASK },
|
||||
{ .name = "ID_AA64ISAR*_EL1_RESERVED",
|
||||
.is_glob = true },
|
||||
};
|
||||
|
||||
@@ -1272,6 +1272,61 @@ FIELD(MTEDESC, SIZEM1, 12, SIMD_DATA_BITS - 12) /* size - 1 */
|
||||
bool mte_probe(CPUARMState *env, uint32_t desc, uint64_t ptr);
|
||||
uint64_t mte_check(CPUARMState *env, uint32_t desc, uint64_t ptr, uintptr_t ra);
|
||||
|
||||
/**
|
||||
* mte_mops_probe: Check where the next MTE failure is for a FEAT_MOPS operation
|
||||
* @env: CPU env
|
||||
* @ptr: start address of memory region (dirty pointer)
|
||||
* @size: length of region (guaranteed not to cross a page boundary)
|
||||
* @desc: MTEDESC descriptor word (0 means no MTE checks)
|
||||
* Returns: the size of the region that can be copied without hitting
|
||||
* an MTE tag failure
|
||||
*
|
||||
* Note that we assume that the caller has already checked the TBI
|
||||
* and TCMA bits with mte_checks_needed() and an MTE check is definitely
|
||||
* required.
|
||||
*/
|
||||
uint64_t mte_mops_probe(CPUARMState *env, uint64_t ptr, uint64_t size,
|
||||
uint32_t desc);
|
||||
|
||||
/**
|
||||
* mte_mops_probe_rev: Check where the next MTE failure is for a FEAT_MOPS
|
||||
* operation going in the reverse direction
|
||||
* @env: CPU env
|
||||
* @ptr: *end* address of memory region (dirty pointer)
|
||||
* @size: length of region (guaranteed not to cross a page boundary)
|
||||
* @desc: MTEDESC descriptor word (0 means no MTE checks)
|
||||
* Returns: the size of the region that can be copied without hitting
|
||||
* an MTE tag failure
|
||||
*
|
||||
* Note that we assume that the caller has already checked the TBI
|
||||
* and TCMA bits with mte_checks_needed() and an MTE check is definitely
|
||||
* required.
|
||||
*/
|
||||
uint64_t mte_mops_probe_rev(CPUARMState *env, uint64_t ptr, uint64_t size,
|
||||
uint32_t desc);
|
||||
|
||||
/**
|
||||
* mte_check_fail: Record an MTE tag check failure
|
||||
* @env: CPU env
|
||||
* @desc: MTEDESC descriptor word
|
||||
* @dirty_ptr: Failing dirty address
|
||||
* @ra: TCG retaddr
|
||||
*
|
||||
* This may never return (if the MTE tag checks are configured to fault).
|
||||
*/
|
||||
void mte_check_fail(CPUARMState *env, uint32_t desc,
|
||||
uint64_t dirty_ptr, uintptr_t ra);
|
||||
|
||||
/**
|
||||
* mte_mops_set_tags: Set MTE tags for a portion of a FEAT_MOPS operation
|
||||
* @env: CPU env
|
||||
* @dirty_ptr: Start address of memory region (dirty pointer)
|
||||
* @size: length of region (guaranteed not to cross page boundary)
|
||||
* @desc: MTEDESC descriptor word
|
||||
*/
|
||||
void mte_mops_set_tags(CPUARMState *env, uint64_t dirty_ptr, uint64_t size,
|
||||
uint32_t desc);
|
||||
|
||||
static inline int allocation_tag_from_addr(uint64_t ptr)
|
||||
{
|
||||
return extract64(ptr, 56, 4);
|
||||
|
||||
@@ -58,6 +58,7 @@ enum arm_exception_class {
|
||||
EC_DATAABORT = 0x24,
|
||||
EC_DATAABORT_SAME_EL = 0x25,
|
||||
EC_SPALIGNMENT = 0x26,
|
||||
EC_MOP = 0x27,
|
||||
EC_AA32_FPTRAP = 0x28,
|
||||
EC_AA64_FPTRAP = 0x2c,
|
||||
EC_SERROR = 0x2f,
|
||||
@@ -334,4 +335,15 @@ static inline uint32_t syn_serror(uint32_t extra)
|
||||
return (EC_SERROR << ARM_EL_EC_SHIFT) | ARM_EL_IL | extra;
|
||||
}
|
||||
|
||||
static inline uint32_t syn_mop(bool is_set, bool is_setg, int options,
|
||||
bool epilogue, bool wrong_option, bool option_a,
|
||||
int destreg, int srcreg, int sizereg)
|
||||
{
|
||||
return (EC_MOP << ARM_EL_EC_SHIFT) | ARM_EL_IL |
|
||||
(is_set << 24) | (is_setg << 23) | (options << 19) |
|
||||
(epilogue << 18) | (wrong_option << 17) | (option_a << 16) |
|
||||
(destreg << 10) | (srcreg << 5) | sizereg;
|
||||
}
|
||||
|
||||
|
||||
#endif /* TARGET_ARM_SYNDROME_H */
|
||||
|
||||
@@ -126,7 +126,8 @@ CBZ sf:1 011010 nz:1 ................... rt:5 &cbz imm=%imm19
|
||||
|
||||
TBZ . 011011 nz:1 ..... .............. rt:5 &tbz imm=%imm14 bitpos=%imm31_19
|
||||
|
||||
B_cond 0101010 0 ................... 0 cond:4 imm=%imm19
|
||||
# B.cond and BC.cond
|
||||
B_cond 0101010 0 ................... c:1 cond:4 imm=%imm19
|
||||
|
||||
BR 1101011 0000 11111 000000 rn:5 00000 &r
|
||||
BLR 1101011 0001 11111 000000 rn:5 00000 &r
|
||||
@@ -553,3 +554,38 @@ LDGM 11011001 11 1 ......... 00 ..... ..... @ldst_tag_mult p=0 w=0
|
||||
STZ2G 11011001 11 1 ......... 01 ..... ..... @ldst_tag p=1 w=1
|
||||
STZ2G 11011001 11 1 ......... 10 ..... ..... @ldst_tag p=0 w=0
|
||||
STZ2G 11011001 11 1 ......... 11 ..... ..... @ldst_tag p=0 w=1
|
||||
|
||||
# Memory operations (memset, memcpy, memmove)
|
||||
# Each of these comes in a set of three, eg SETP (prologue), SETM (main),
|
||||
# SETE (epilogue), and each of those has different flavours to
|
||||
# indicate whether memory accesses should be unpriv or non-temporal.
|
||||
# We don't distinguish temporal and non-temporal accesses, but we
|
||||
# do need to report it in syndrome register values.
|
||||
|
||||
# Memset
|
||||
&set rs rn rd unpriv nontemp
|
||||
# op2 bit 1 is nontemporal bit
|
||||
@set .. ......... rs:5 .. nontemp:1 unpriv:1 .. rn:5 rd:5 &set
|
||||
|
||||
SETP 00 011001110 ..... 00 . . 01 ..... ..... @set
|
||||
SETM 00 011001110 ..... 01 . . 01 ..... ..... @set
|
||||
SETE 00 011001110 ..... 10 . . 01 ..... ..... @set
|
||||
|
||||
# Like SET, but also setting MTE tags
|
||||
SETGP 00 011101110 ..... 00 . . 01 ..... ..... @set
|
||||
SETGM 00 011101110 ..... 01 . . 01 ..... ..... @set
|
||||
SETGE 00 011101110 ..... 10 . . 01 ..... ..... @set
|
||||
|
||||
# Memmove/Memcopy: the CPY insns allow overlapping src/dest and
|
||||
# copy in the correct direction; the CPYF insns always copy forwards.
|
||||
#
|
||||
# options has the nontemporal and unpriv bits for src and dest
|
||||
&cpy rs rn rd options
|
||||
@cpy .. ... . ..... rs:5 options:4 .. rn:5 rd:5 &cpy
|
||||
|
||||
CPYFP 00 011 0 01000 ..... .... 01 ..... ..... @cpy
|
||||
CPYFM 00 011 0 01010 ..... .... 01 ..... ..... @cpy
|
||||
CPYFE 00 011 0 01100 ..... .... 01 ..... ..... @cpy
|
||||
CPYP 00 011 1 01000 ..... .... 01 ..... ..... @cpy
|
||||
CPYM 00 011 1 01010 ..... .... 01 ..... ..... @cpy
|
||||
CPYE 00 011 1 01100 ..... .... 01 ..... ..... @cpy
|
||||
|
||||
@@ -1027,6 +1027,11 @@ void aarch64_max_tcg_initfn(Object *obj)
|
||||
t = FIELD_DP64(t, ID_AA64ISAR1, I8MM, 1); /* FEAT_I8MM */
|
||||
cpu->isar.id_aa64isar1 = t;
|
||||
|
||||
t = cpu->isar.id_aa64isar2;
|
||||
t = FIELD_DP64(t, ID_AA64ISAR2, MOPS, 1); /* FEAT_MOPS */
|
||||
t = FIELD_DP64(t, ID_AA64ISAR2, BC, 1); /* FEAT_HBC */
|
||||
cpu->isar.id_aa64isar2 = t;
|
||||
|
||||
t = cpu->isar.id_aa64pfr0;
|
||||
t = FIELD_DP64(t, ID_AA64PFR0, FP, 1); /* FEAT_FP16 */
|
||||
t = FIELD_DP64(t, ID_AA64PFR0, ADVSIMD, 1); /* FEAT_FP16 */
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user