From c076406450f46df3806015d44605e45be89673a7 Mon Sep 17 00:00:00 2001 From: RichardG867 Date: Sat, 22 Apr 2023 18:41:42 -0300 Subject: [PATCH] 386_common: Optimize I/O permission checking for word and dword operations (based on qemu) --- src/cpu/386_common.c | 19 ++++++++++--------- src/cpu/386_common.h | 6 +++--- src/cpu/cpu.h | 2 +- src/cpu/x86_ops_io.h | 40 ++++++++++++--------------------------- src/cpu/x86_ops_rep.h | 20 ++++++-------------- src/cpu/x86_ops_rep_dyn.h | 20 ++++++-------------- src/cpu/x86_ops_string.h | 40 ++++++++++++--------------------------- 7 files changed, 50 insertions(+), 97 deletions(-) diff --git a/src/cpu/386_common.c b/src/cpu/386_common.c index 2df72c20e..454815de0 100644 --- a/src/cpu/386_common.c +++ b/src/cpu/386_common.c @@ -1427,25 +1427,26 @@ x86illegal(void) } int -checkio(uint32_t port) +checkio(uint32_t port, int mask) { uint16_t t; - uint8_t d; cpl_override = 1; t = readmemw(tr.base, 0x66); - cpl_override = 0; - if (cpu_state.abrt) + if (cpu_state.abrt) { + cpl_override = 0; return 0; + } - if ((t + (port >> 3UL)) > tr.limit) - return 1; + if ((t + (port >> 3UL) + 1) > tr.limit) { + cpl_override = 0; + return mask; + } - cpl_override = 1; - d = readmembl(tr.base + t + (port >> 3)); + t = readmemwl(tr.base + t + (port >> 3)); cpl_override = 0; - return d & (1 << (port & 7)); + return (t >> (port & 7)) & mask; } #ifdef OLD_DIVEXCP diff --git a/src/cpu/386_common.h b/src/cpu/386_common.h index f26eb7f98..ae71347b6 100644 --- a/src/cpu/386_common.h +++ b/src/cpu/386_common.h @@ -97,11 +97,11 @@ if (writelookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 3)) \ do_mmutranslate((s) + (a), b, 4, 1) -int checkio(uint32_t port); +int checkio(uint32_t port, int mask); -#define check_io_perm(port) \ +#define check_io_perm(port, size) \ if (msw & 1 && ((CPL > IOPL) || (cpu_state.eflags & VM_FLAG))) { \ - int tempi = checkio(port); \ + int tempi = checkio(port, (1 << size) - 1); \ if (cpu_state.abrt) \ return 1; \ if (tempi) { \ diff --git a/src/cpu/cpu.h b/src/cpu/cpu.h index 93dae98d1..f8ffaced3 100644 --- a/src/cpu/cpu.h +++ b/src/cpu/cpu.h @@ -642,7 +642,7 @@ extern void cpu_CPUID(void); extern void cpu_RDMSR(void); extern void cpu_WRMSR(void); -extern int checkio(uint32_t port); +extern int checkio(uint32_t port, int mask); extern void codegen_block_end(void); extern void codegen_reset(void); extern void cpu_set_edx(void); diff --git a/src/cpu/x86_ops_io.h b/src/cpu/x86_ops_io.h index c4d46404d..8a99b8668 100644 --- a/src/cpu/x86_ops_io.h +++ b/src/cpu/x86_ops_io.h @@ -2,7 +2,7 @@ static int opIN_AL_imm(uint32_t fetchdat) { uint16_t port = (uint16_t) getbytef(); - check_io_perm(port); + check_io_perm(port, 1); AL = inb(port); CLOCK_CYCLES(12); PREFETCH_RUN(12, 2, -1, 1, 0, 0, 0, 0); @@ -14,8 +14,7 @@ static int opIN_AX_imm(uint32_t fetchdat) { uint16_t port = (uint16_t) getbytef(); - check_io_perm(port); - check_io_perm(port + 1); + check_io_perm(port, 2); AX = inw(port); CLOCK_CYCLES(12); PREFETCH_RUN(12, 2, -1, 1, 0, 0, 0, 0); @@ -27,10 +26,7 @@ static int opIN_EAX_imm(uint32_t fetchdat) { uint16_t port = (uint16_t) getbytef(); - check_io_perm(port); - check_io_perm(port + 1); - check_io_perm(port + 2); - check_io_perm(port + 3); + check_io_perm(port, 4); EAX = inl(port); CLOCK_CYCLES(12); PREFETCH_RUN(12, 2, -1, 0, 1, 0, 0, 0); @@ -43,7 +39,7 @@ static int opOUT_AL_imm(uint32_t fetchdat) { uint16_t port = (uint16_t) getbytef(); - check_io_perm(port); + check_io_perm(port, 1); outb(port, AL); CLOCK_CYCLES(10); PREFETCH_RUN(10, 2, -1, 0, 0, 1, 0, 0); @@ -57,8 +53,7 @@ static int opOUT_AX_imm(uint32_t fetchdat) { uint16_t port = (uint16_t) getbytef(); - check_io_perm(port); - check_io_perm(port + 1); + check_io_perm(port, 2); outw(port, AX); CLOCK_CYCLES(10); PREFETCH_RUN(10, 2, -1, 0, 0, 1, 0, 0); @@ -70,10 +65,7 @@ static int opOUT_EAX_imm(uint32_t fetchdat) { uint16_t port = (uint16_t) getbytef(); - check_io_perm(port); - check_io_perm(port + 1); - check_io_perm(port + 2); - check_io_perm(port + 3); + check_io_perm(port, 4); outl(port, EAX); CLOCK_CYCLES(10); PREFETCH_RUN(10, 2, -1, 0, 0, 0, 1, 0); @@ -85,7 +77,7 @@ opOUT_EAX_imm(uint32_t fetchdat) static int opIN_AL_DX(uint32_t fetchdat) { - check_io_perm(DX); + check_io_perm(DX, 1); AL = inb(DX); CLOCK_CYCLES(12); PREFETCH_RUN(12, 1, -1, 1, 0, 0, 0, 0); @@ -96,8 +88,7 @@ opIN_AL_DX(uint32_t fetchdat) static int opIN_AX_DX(uint32_t fetchdat) { - check_io_perm(DX); - check_io_perm(DX + 1); + check_io_perm(DX, 2); AX = inw(DX); CLOCK_CYCLES(12); PREFETCH_RUN(12, 1, -1, 1, 0, 0, 0, 0); @@ -108,10 +99,7 @@ opIN_AX_DX(uint32_t fetchdat) static int opIN_EAX_DX(uint32_t fetchdat) { - check_io_perm(DX); - check_io_perm(DX + 1); - check_io_perm(DX + 2); - check_io_perm(DX + 3); + check_io_perm(DX, 4); EAX = inl(DX); CLOCK_CYCLES(12); PREFETCH_RUN(12, 1, -1, 0, 1, 0, 0, 0); @@ -123,7 +111,7 @@ opIN_EAX_DX(uint32_t fetchdat) static int opOUT_AL_DX(uint32_t fetchdat) { - check_io_perm(DX); + check_io_perm(DX, 1); outb(DX, AL); CLOCK_CYCLES(11); PREFETCH_RUN(11, 1, -1, 0, 0, 1, 0, 0); @@ -134,8 +122,7 @@ opOUT_AL_DX(uint32_t fetchdat) static int opOUT_AX_DX(uint32_t fetchdat) { - check_io_perm(DX); - check_io_perm(DX + 1); + check_io_perm(DX, 2); outw(DX, AX); CLOCK_CYCLES(11); PREFETCH_RUN(11, 1, -1, 0, 0, 1, 0, 0); @@ -146,10 +133,7 @@ opOUT_AX_DX(uint32_t fetchdat) static int opOUT_EAX_DX(uint32_t fetchdat) { - check_io_perm(DX); - check_io_perm(DX + 1); - check_io_perm(DX + 2); - check_io_perm(DX + 3); + check_io_perm(DX, 4); outl(DX, EAX); PREFETCH_RUN(11, 1, -1, 0, 0, 0, 1, 0); if (nmi && nmi_enable && nmi_mask) diff --git a/src/cpu/x86_ops_rep.h b/src/cpu/x86_ops_rep.h index 67bd8433d..4b8f42185 100644 --- a/src/cpu/x86_ops_rep.h +++ b/src/cpu/x86_ops_rep.h @@ -9,7 +9,7 @@ uint8_t temp; \ \ SEG_CHECK_WRITE(&cpu_state.seg_es); \ - check_io_perm(DX); \ + check_io_perm(DX, 1); \ CHECK_WRITE(&cpu_state.seg_es, DEST_REG, DEST_REG); \ high_page = 0; \ do_mmut_wb(es, DEST_REG, &addr64); \ @@ -48,8 +48,7 @@ uint16_t temp; \ \ SEG_CHECK_WRITE(&cpu_state.seg_es); \ - check_io_perm(DX); \ - check_io_perm(DX + 1); \ + check_io_perm(DX, 2); \ CHECK_WRITE(&cpu_state.seg_es, DEST_REG, DEST_REG + 1UL); \ high_page = 0; \ do_mmut_ww(es, DEST_REG, addr64a); \ @@ -88,10 +87,7 @@ uint32_t temp; \ \ SEG_CHECK_WRITE(&cpu_state.seg_es); \ - check_io_perm(DX); \ - check_io_perm(DX + 1); \ - check_io_perm(DX + 2); \ - check_io_perm(DX + 3); \ + check_io_perm(DX, 4); \ CHECK_WRITE(&cpu_state.seg_es, DEST_REG, DEST_REG + 3UL); \ high_page = 0; \ do_mmut_wl(es, DEST_REG, addr64a); \ @@ -132,7 +128,7 @@ temp = readmemb(cpu_state.ea_seg->base, SRC_REG); \ if (cpu_state.abrt) \ return 1; \ - check_io_perm(DX); \ + check_io_perm(DX, 1); \ outb(DX, temp); \ if (cpu_state.flags & D_FLAG) \ SRC_REG--; \ @@ -163,8 +159,7 @@ temp = readmemw(cpu_state.ea_seg->base, SRC_REG); \ if (cpu_state.abrt) \ return 1; \ - check_io_perm(DX); \ - check_io_perm(DX + 1); \ + check_io_perm(DX, 2); \ outw(DX, temp); \ if (cpu_state.flags & D_FLAG) \ SRC_REG -= 2; \ @@ -195,10 +190,7 @@ temp = readmeml(cpu_state.ea_seg->base, SRC_REG); \ if (cpu_state.abrt) \ return 1; \ - check_io_perm(DX); \ - check_io_perm(DX + 1); \ - check_io_perm(DX + 2); \ - check_io_perm(DX + 3); \ + check_io_perm(DX, 4); \ outl(DX, temp); \ if (cpu_state.flags & D_FLAG) \ SRC_REG -= 4; \ diff --git a/src/cpu/x86_ops_rep_dyn.h b/src/cpu/x86_ops_rep_dyn.h index 576baa403..5c64ed94d 100644 --- a/src/cpu/x86_ops_rep_dyn.h +++ b/src/cpu/x86_ops_rep_dyn.h @@ -7,7 +7,7 @@ uint8_t temp; \ \ SEG_CHECK_WRITE(&cpu_state.seg_es); \ - check_io_perm(DX); \ + check_io_perm(DX, 1); \ CHECK_WRITE(&cpu_state.seg_es, DEST_REG, DEST_REG); \ high_page = 0; \ do_mmut_wb(es, DEST_REG, &addr64); \ @@ -40,8 +40,7 @@ uint16_t temp; \ \ SEG_CHECK_WRITE(&cpu_state.seg_es); \ - check_io_perm(DX); \ - check_io_perm(DX + 1); \ + check_io_perm(DX, 2); \ CHECK_WRITE(&cpu_state.seg_es, DEST_REG, DEST_REG + 1UL); \ high_page = 0; \ do_mmut_ww(es, DEST_REG, addr64a); \ @@ -74,10 +73,7 @@ uint32_t temp; \ \ SEG_CHECK_WRITE(&cpu_state.seg_es); \ - check_io_perm(DX); \ - check_io_perm(DX + 1); \ - check_io_perm(DX + 2); \ - check_io_perm(DX + 3); \ + check_io_perm(DX, 4); \ CHECK_WRITE(&cpu_state.seg_es, DEST_REG, DEST_REG + 3UL); \ high_page = 0; \ do_mmut_wl(es, DEST_REG, addr64a); \ @@ -112,7 +108,7 @@ temp = readmemb(cpu_state.ea_seg->base, SRC_REG); \ if (cpu_state.abrt) \ return 1; \ - check_io_perm(DX); \ + check_io_perm(DX, 1); \ outb(DX, temp); \ if (cpu_state.flags & D_FLAG) \ SRC_REG--; \ @@ -137,8 +133,7 @@ temp = readmemw(cpu_state.ea_seg->base, SRC_REG); \ if (cpu_state.abrt) \ return 1; \ - check_io_perm(DX); \ - check_io_perm(DX + 1); \ + check_io_perm(DX, 2); \ outw(DX, temp); \ if (cpu_state.flags & D_FLAG) \ SRC_REG -= 2; \ @@ -163,10 +158,7 @@ temp = readmeml(cpu_state.ea_seg->base, SRC_REG); \ if (cpu_state.abrt) \ return 1; \ - check_io_perm(DX); \ - check_io_perm(DX + 1); \ - check_io_perm(DX + 2); \ - check_io_perm(DX + 3); \ + check_io_perm(DX, 4); \ outl(DX, temp); \ if (cpu_state.flags & D_FLAG) \ SRC_REG -= 4; \ diff --git a/src/cpu/x86_ops_string.h b/src/cpu/x86_ops_string.h index 5cc5f3806..c3875a648 100644 --- a/src/cpu/x86_ops_string.h +++ b/src/cpu/x86_ops_string.h @@ -804,7 +804,7 @@ opINSB_a16(uint32_t fetchdat) addr64 = 0x00000000; SEG_CHECK_WRITE(&cpu_state.seg_es); - check_io_perm(DX); + check_io_perm(DX, 1); CHECK_WRITE(&cpu_state.seg_es, DI, DI); high_page = 0; do_mmut_wb(es, DI, &addr64); @@ -830,7 +830,7 @@ opINSB_a32(uint32_t fetchdat) addr64 = 0x00000000; SEG_CHECK_WRITE(&cpu_state.seg_es); - check_io_perm(DX); + check_io_perm(DX, 1); high_page = 0; CHECK_WRITE(&cpu_state.seg_es, EDI, EDI); do_mmut_wb(es, EDI, &addr64); @@ -857,8 +857,7 @@ opINSW_a16(uint32_t fetchdat) addr64a[0] = addr64a[1] = 0x00000000; SEG_CHECK_WRITE(&cpu_state.seg_es); - check_io_perm(DX); - check_io_perm(DX + 1); + check_io_perm(DX, 2); CHECK_WRITE(&cpu_state.seg_es, DI, DI + 1UL); high_page = 0; do_mmut_ww(es, DI, addr64a); @@ -885,8 +884,7 @@ opINSW_a32(uint32_t fetchdat) SEG_CHECK_WRITE(&cpu_state.seg_es); high_page = 0; - check_io_perm(DX); - check_io_perm(DX + 1); + check_io_perm(DX, 2); CHECK_WRITE(&cpu_state.seg_es, EDI, EDI + 1UL); do_mmut_ww(es, EDI, addr64a); if (cpu_state.abrt) @@ -912,10 +910,7 @@ opINSL_a16(uint32_t fetchdat) addr64a[0] = addr64a[1] = addr64a[2] = addr64a[3] = 0x00000000; SEG_CHECK_WRITE(&cpu_state.seg_es); - check_io_perm(DX); - check_io_perm(DX + 1); - check_io_perm(DX + 2); - check_io_perm(DX + 3); + check_io_perm(DX, 4); CHECK_WRITE(&cpu_state.seg_es, DI, DI + 3UL); high_page = 0; do_mmut_wl(es, DI, addr64a); @@ -941,10 +936,7 @@ opINSL_a32(uint32_t fetchdat) addr64a[0] = addr64a[1] = addr64a[2] = addr64a[3] = 0x00000000; SEG_CHECK_WRITE(&cpu_state.seg_es); - check_io_perm(DX); - check_io_perm(DX + 1); - check_io_perm(DX + 2); - check_io_perm(DX + 3); + check_io_perm(DX, 4); CHECK_WRITE(&cpu_state.seg_es, EDI, EDI + 3UL); high_page = 0; do_mmut_wl(es, DI, addr64a); @@ -973,7 +965,7 @@ opOUTSB_a16(uint32_t fetchdat) temp = readmemb(cpu_state.ea_seg->base, SI); if (cpu_state.abrt) return 1; - check_io_perm(DX); + check_io_perm(DX, 1); if (cpu_state.flags & D_FLAG) SI--; else @@ -993,7 +985,7 @@ opOUTSB_a32(uint32_t fetchdat) temp = readmemb(cpu_state.ea_seg->base, ESI); if (cpu_state.abrt) return 1; - check_io_perm(DX); + check_io_perm(DX, 1); if (cpu_state.flags & D_FLAG) ESI--; else @@ -1014,8 +1006,7 @@ opOUTSW_a16(uint32_t fetchdat) temp = readmemw(cpu_state.ea_seg->base, SI); if (cpu_state.abrt) return 1; - check_io_perm(DX); - check_io_perm(DX + 1); + check_io_perm(DX, 2); if (cpu_state.flags & D_FLAG) SI -= 2; else @@ -1035,8 +1026,7 @@ opOUTSW_a32(uint32_t fetchdat) temp = readmemw(cpu_state.ea_seg->base, ESI); if (cpu_state.abrt) return 1; - check_io_perm(DX); - check_io_perm(DX + 1); + check_io_perm(DX, 2); if (cpu_state.flags & D_FLAG) ESI -= 2; else @@ -1057,10 +1047,7 @@ opOUTSL_a16(uint32_t fetchdat) temp = readmeml(cpu_state.ea_seg->base, SI); if (cpu_state.abrt) return 1; - check_io_perm(DX); - check_io_perm(DX + 1); - check_io_perm(DX + 2); - check_io_perm(DX + 3); + check_io_perm(DX, 4); if (cpu_state.flags & D_FLAG) SI -= 4; else @@ -1080,10 +1067,7 @@ opOUTSL_a32(uint32_t fetchdat) temp = readmeml(cpu_state.ea_seg->base, ESI); if (cpu_state.abrt) return 1; - check_io_perm(DX); - check_io_perm(DX + 1); - check_io_perm(DX + 2); - check_io_perm(DX + 3); + check_io_perm(DX, 4); if (cpu_state.flags & D_FLAG) ESI -= 4; else