QEMU main repository: Please see https://www.qemu.org/docs/master/devel/submitting-a-patch.html for how to submit changes to QEMU. Pull Requests are ignored. Please only use release tarballs from the QEMU website. http://www.qemu.org
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
106 lines
2.5 KiB
106 lines
2.5 KiB
/*
|
|
* Test that invalid instruction encodings are properly rejected.
|
|
*
|
|
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
|
|
* SPDX-License-Identifier: GPL-2.0-or-later
|
|
*/
|
|
|
|
#include <assert.h>
|
|
#include <signal.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
|
|
static void *resume_pc;
|
|
|
|
static void handle_sigill(int sig, siginfo_t *info, void *puc)
|
|
{
|
|
ucontext_t *uc = (ucontext_t *)puc;
|
|
|
|
if (sig != SIGILL) {
|
|
_exit(EXIT_FAILURE);
|
|
}
|
|
|
|
uc->uc_mcontext.r0 = SIGILL;
|
|
uc->uc_mcontext.pc = (unsigned long)resume_pc;
|
|
}
|
|
|
|
/*
|
|
* Each test function:
|
|
* - Sets r0 to something other than SIGILL
|
|
* - Stores the resume address into resume_pc
|
|
* - Executes the invalid encoding
|
|
* - The handler sets r0 = SIGILL and resumes after the faulting packet
|
|
* - Returns the value in r0
|
|
*/
|
|
|
|
/*
|
|
* Invalid duplex encoding (issue #3291):
|
|
* - Word 0: 0x0fff6fff = immext(#0xfffbffc0), parse bits = 01
|
|
* - Word 1: 0x600237b0 = duplex with:
|
|
* - slot0 = 0x17b0 (invalid S2 subinstruction encoding)
|
|
* - slot1 = 0x0002 (valid SA1_addi)
|
|
* - duplex iclass = 7 (S2 for slot0, A for slot1)
|
|
*
|
|
* Since slot0 doesn't decode to any valid S2 subinstruction, this packet
|
|
* should be rejected and raise SIGILL.
|
|
*/
|
|
static int test_invalid_duplex(void)
|
|
{
|
|
int sig;
|
|
|
|
asm volatile(
|
|
"r0 = #0\n"
|
|
"r1 = ##1f\n"
|
|
"memw(%1) = r1\n"
|
|
".word 0x0fff6fff\n" /* immext(#0xfffbffc0), parse=01 */
|
|
".word 0x600237b0\n" /* duplex: slot0=0x17b0 (invalid) */
|
|
"1:\n"
|
|
"%0 = r0\n"
|
|
: "=r"(sig)
|
|
: "r"(&resume_pc)
|
|
: "r0", "r1", "memory");
|
|
|
|
return sig;
|
|
}
|
|
|
|
/*
|
|
* Invalid non-duplex encoding:
|
|
* The encoding 0xffffc000 has parse bits [15:14] = 0b11, making it a
|
|
* non-duplex instruction and packet end. The remaining bits do not match
|
|
* any valid normal or HVX instruction encoding, so this should raise SIGILL.
|
|
*/
|
|
static int test_invalid_nonduplex(void)
|
|
{
|
|
int sig;
|
|
|
|
asm volatile(
|
|
"r0 = #0\n"
|
|
"r1 = ##1f\n"
|
|
"memw(%1) = r1\n"
|
|
".word 0xffffc000\n"
|
|
"1:\n"
|
|
"%0 = r0\n"
|
|
: "=r"(sig)
|
|
: "r"(&resume_pc)
|
|
: "r0", "r1", "memory");
|
|
|
|
return sig;
|
|
}
|
|
|
|
int main()
|
|
{
|
|
struct sigaction act;
|
|
|
|
memset(&act, 0, sizeof(act));
|
|
act.sa_sigaction = handle_sigill;
|
|
act.sa_flags = SA_SIGINFO;
|
|
assert(sigaction(SIGILL, &act, NULL) == 0);
|
|
|
|
assert(test_invalid_duplex() == SIGILL);
|
|
assert(test_invalid_nonduplex() == SIGILL);
|
|
|
|
puts("PASS");
|
|
return EXIT_SUCCESS;
|
|
}
|
|
|