mirror of https://gitlab.com/qemu-project/qemu
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
83 lines
1.6 KiB
C
83 lines
1.6 KiB
C
/*
|
|
* Test modifying code using the MVC instruction.
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0-or-later
|
|
*/
|
|
|
|
#include <minilib.h>
|
|
|
|
#define PAGE_SIZE 4096
|
|
#define BR_14_SIZE 2
|
|
#define RWX_OFFSET 2
|
|
|
|
static unsigned char rw[PAGE_SIZE + BR_14_SIZE];
|
|
static unsigned char rwx[RWX_OFFSET + sizeof(rw)]
|
|
__attribute__((aligned(PAGE_SIZE)));
|
|
|
|
typedef unsigned long (*function_t)(unsigned long);
|
|
|
|
static int emit_function(unsigned char *p, int n)
|
|
{
|
|
int i = 0, val = 0;
|
|
|
|
while (i < n - 2) {
|
|
/* aghi %r2,1 */
|
|
p[i++] = 0xa7;
|
|
p[i++] = 0x2b;
|
|
p[i++] = 0x00;
|
|
p[i++] = 0x01;
|
|
val++;
|
|
}
|
|
|
|
/* br %r14 */
|
|
p[i++] = 0x07;
|
|
p[i++] = 0xfe;
|
|
|
|
return val;
|
|
}
|
|
|
|
static void memcpy_mvc(void *dest, void *src, unsigned long n)
|
|
{
|
|
while (n >= 256) {
|
|
asm("mvc 0(256,%[dest]),0(%[src])"
|
|
:
|
|
: [dest] "a" (dest)
|
|
, [src] "a" (src)
|
|
: "memory");
|
|
dest += 256;
|
|
src += 256;
|
|
n -= 256;
|
|
}
|
|
asm("exrl %[n],0f\n"
|
|
"j 1f\n"
|
|
"0: mvc 0(1,%[dest]),0(%[src])\n"
|
|
"1:"
|
|
:
|
|
: [dest] "a" (dest)
|
|
, [src] "a" (src)
|
|
, [n] "a" (n)
|
|
: "memory");
|
|
}
|
|
|
|
int main(void)
|
|
{
|
|
int expected, size;
|
|
|
|
/* Create a TB. */
|
|
size = sizeof(rwx) - RWX_OFFSET - 4;
|
|
expected = emit_function(rwx + RWX_OFFSET, size);
|
|
if (((function_t)(rwx + RWX_OFFSET))(0) != expected) {
|
|
return 1;
|
|
}
|
|
|
|
/* Overwrite the TB. */
|
|
size += 4;
|
|
expected = emit_function(rw, size);
|
|
memcpy_mvc(rwx + RWX_OFFSET, rw, size);
|
|
if (((function_t)(rwx + RWX_OFFSET))(0) != expected) {
|
|
return 2;
|
|
}
|
|
|
|
return 0;
|
|
}
|