From eee8ce6c7d5978d8146c3f5b81843b57fa687039 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Wed, 27 Jul 2022 13:57:03 -0400 Subject: [PATCH] A couple of fixes --- src/cpu/cpu.c | 87 ++++++------ src/include/86box/machine.h | 3 +- src/machine/m_at_slot1.c | 93 +++++++++++-- src/machine/machine_table.c | 68 ++++++++++ src/mem/mem.c | 256 ++++++++++++++++++++++++++++++++++++ 5 files changed, 451 insertions(+), 56 deletions(-) diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c index 9942269bf..fdb8809eb 100644 --- a/src/cpu/cpu.c +++ b/src/cpu/cpu.c @@ -150,6 +150,11 @@ void (*cpu_exec)(int cycs); static uint8_t ccr0, ccr1, ccr2, ccr3, ccr4, ccr5, ccr6; +void cpu_INVD(uint8_t wb) +{ + mem_invalidate_mtrr(wb); +} + static int cyrix_addr; @@ -2174,24 +2179,14 @@ cpu_RDMSR(void) case 0x204: case 0x205: case 0x206: case 0x207: case 0x208: case 0x209: case 0x20a: case 0x20b: case 0x20c: case 0x20d: case 0x20e: case 0x20f: - temp = EAX | ((uint64_t)EDX << 32); - temp2 = (ECX - 0x200) >> 1; - if (ECX & 1) { - cpu_log("MTRR physmask[%d] = %08llx\n", temp2, temp); - - if ((mtrr_physmask_msr[temp2] >> 11) & 0x1) - mem_del_mtrr(mtrr_physbase_msr[temp2] & ~(0xFFF), mtrr_physmask_msr[temp2] & ~(0xFFF)); - - if ((temp >> 11) & 0x1) - mem_add_mtrr(mtrr_physbase_msr[temp2] & ~(0xFFF), temp & ~(0xFFF), mtrr_physbase_msr[temp2] & 0xFF); - - mtrr_physmask_msr[temp2] = temp; - } else { - cpu_log("MTRR physbase[%d] = %08llx\n", temp2, temp); - - mtrr_physbase_msr[temp2] = temp; - } - break; + if (ECX & 1) { + EAX = msr.mtrr_physmask[(ECX - 0x200) >> 1] & 0xffffffff; + EDX = msr.mtrr_physmask[(ECX - 0x200) >> 1] >> 32; + } else { + EAX = msr.mtrr_physbase[(ECX - 0x200) >> 1] & 0xffffffff; + EDX = msr.mtrr_physbase[(ECX - 0x200) >> 1] >> 32; + } + break; case 0x250: EAX = msr.mtrr_fix64k_8000 & 0xffffffff; EDX = msr.mtrr_fix64k_8000 >> 32; @@ -2625,23 +2620,24 @@ cpu_WRMSR(void) case 0x204: case 0x205: case 0x206: case 0x207: case 0x208: case 0x209: case 0x20a: case 0x20b: case 0x20c: case 0x20d: case 0x20e: case 0x20f: - temp = EAX | ((uint64_t)EDX << 32); - temp2 = (ECX - 0x200) >> 1; - if (ECX & 1) { - cpu_log("MTRR physmask[%d] = %08llx\n", temp2, temp); + temp = EAX | ((uint64_t)EDX << 32); + temp2 = (ECX - 0x200) >> 1; + if (ECX & 1) { + cpu_log("MTRR physmask[%d] = %08llx\n", temp2, temp); - if ((mtrr_physmask_msr[temp2] >> 11) & 0x1) - mem_del_mtrr(mtrr_physbase_msr[temp2] & ~(0xfff), mtrr_physmask_msr[temp2] & ~(0xfff)); + if ((msr.mtrr_physmask[temp2] >> 11) & 0x1) + mem_del_mtrr(msr.mtrr_physbase[temp2] & ~(0xFFF), msr.mtrr_physmask[temp2] & ~(0xFFF)); - if ((temp >> 11) & 0x1) - mem_add_mtrr(mtrr_physbase_msr[temp2] & ~(0xfff), temp & ~(0xfff), mtrr_physbase_msr[temp2] & 0xff); + if ((temp >> 11) & 0x1) + mem_add_mtrr(msr.mtrr_physbase[temp2] & ~(0xFFF), temp & ~(0xFFF), msr.mtrr_physbase[temp2] & 0xFF); - mtrr_physmask_msr[temp2] = temp; - } else { - cpu_log("MTRR physbase[%d] = %08llx\n", temp2, temp); + msr.mtrr_physmask[temp2] = temp; + } else { + cpu_log("MTRR physbase[%d] = %08llx\n", temp2, temp); - mtrr_physbase_msr[temp2] = temp; - } + msr.mtrr_physbase[temp2] = temp; + } + break; case 0x250: msr.mtrr_fix64k_8000 = EAX | ((uint64_t)EDX << 32); break; @@ -2843,11 +2839,24 @@ amd_k_invalid_wrmsr: case 0x204: case 0x205: case 0x206: case 0x207: case 0x208: case 0x209: case 0x20a: case 0x20b: case 0x20c: case 0x20d: case 0x20e: case 0x20f: - if (ECX & 1) - msr.mtrr_physmask[(ECX - 0x200) >> 1] = EAX | ((uint64_t)EDX << 32); - else - msr.mtrr_physbase[(ECX - 0x200) >> 1] = EAX | ((uint64_t)EDX << 32); - break; + temp = EAX | ((uint64_t)EDX << 32); + temp2 = (ECX - 0x200) >> 1; + if (ECX & 1) { + cpu_log("MTRR physmask[%d] = %08llx\n", temp2, temp); + + if ((msr.mtrr_physmask[temp2] >> 11) & 0x1) + mem_del_mtrr(msr.mtrr_physbase[temp2] & ~(0xFFF), msr.mtrr_physmask[temp2] & ~(0xFFF)); + + if ((temp >> 11) & 0x1) + mem_add_mtrr(msr.mtrr_physbase[temp2] & ~(0xFFF), temp & ~(0xFFF), msr.mtrr_physbase[temp2] & 0xFF); + + msr.mtrr_physmask[temp2] = temp; + } else { + cpu_log("MTRR physbase[%d] = %08llx\n", temp2, temp); + + msr.mtrr_physbase[temp2] = temp; + } + break; case 0x250: msr.mtrr_fix64k_8000 = EAX | ((uint64_t)EDX << 32); break; @@ -2902,12 +2911,6 @@ i686_invalid_wrmsr: } } -void cpu_INVD(uint8_t wb) -{ - mem_invalidate_mtrr(wb); -} - -static int cyrix_addr; static void cpu_write(uint16_t addr, uint8_t val, void *priv) diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index 0f3dc86d9..ca5abae02 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -108,7 +108,6 @@ #define MACHINE_USB_PRI 0x04000000 /* sys has int pri USB */ #define MACHINE_USB_SEC 0x08000000 /* sys has int sec USB */ #define MACHINE_COREBOOT 0x10000000 /* sys has coreboot BIOS */ - /* Combined flags. */ #define MACHINE_IDE (MACHINE_IDE_PRI) /* sys has int single IDE/ATAPI - mark as pri IDE/ATAPI */ #define MACHINE_IDE_DUAL (MACHINE_IDE_PRI | MACHINE_IDE_SEC) /* sys has int dual IDE/ATAPI - mark as both pri and sec IDE/ATAPI */ @@ -664,6 +663,8 @@ extern int machine_at_p6i440e2_init(const machine_t *); extern int machine_at_p2bls_init(const machine_t *); extern int machine_at_p3bf_init(const machine_t *); +extern int machine_at_p2bls_coreboot_init(const machine_t *); +extern int machine_at_p3bf_coreboot_init(const machine_t *); extern int machine_at_bf6_init(const machine_t *); extern int machine_at_ax6bc_init(const machine_t *); extern int machine_at_atc6310bxii_init(const machine_t *); diff --git a/src/machine/m_at_slot1.c b/src/machine/m_at_slot1.c index 2ada979c0..3c31f1e0a 100644 --- a/src/machine/m_at_slot1.c +++ b/src/machine/m_at_slot1.c @@ -194,12 +194,46 @@ machine_at_p2bls_init(const machine_t *model) { int ret; - if (model->flags & MACHINE_COREBOOT) - ret = bios_load_linear("roms/machines/p2bls/coreboot.rom", - 0x000c0000, 262144, 0); - else - ret = bios_load_linear("roms/machines/p2bls/1014ls.003", - 0x000c0000, 262144, 0); + ret = bios_load_linear("roms/machines/p2bls/1014ls.003", + 0x000c0000, 262144, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init_ex(model, 2); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x04, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); + pci_register_slot(0x06, PCI_CARD_NORMAL, 4, 1, 2, 3); /* SCSI */ + pci_register_slot(0x07, PCI_CARD_NORMAL, 3, 4, 1, 2); /* LAN */ + pci_register_slot(0x0B, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x09, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x01, PCI_CARD_AGPBRIDGE, 1, 2, 3, 4); + device_add(&i440bx_device); + device_add(&piix4e_device); + device_add(&keyboard_ps2_ami_pci_device); + device_add(&w83977ef_device); + //device_add(ics9xxx_get(ICS9150_08)); /* setting proper speeds requires some interaction with the AS97127F ASIC */ + device_add(&sst_flash_39sf020_device); + spd_register(SPD_TYPE_SDRAM, 0xF, 256); + device_add(&w83781d_device); /* fans: Chassis, CPU, Power; temperatures: MB, unused, CPU */ + hwm_values.temperatures[1] = 0; /* unused */ + hwm_values.temperatures[2] -= 3; /* CPU offset */ + + return ret; +} + + +int +machine_at_p2bls_coreboot_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/p2bls/coreboot.rom", + 0x000c0000, 262144, 0); if (bios_only || !ret) return ret; @@ -236,13 +270,46 @@ machine_at_p3bf_init(const machine_t *model) { int ret; - if (model->flags & MACHINE_COREBOOT) - ret = bios_load_linear("roms/machines/p3bf/coreboot.rom", - 0x000c0000, 262144, 0); - else -// ret = bios_load_linear("roms/machines/p3bf/bx3f1006.awd", - ret = bios_load_linear("roms/machines/p3bf/1008f.004", - 0x000c0000, 262144, 0); +// ret = bios_load_linear("roms/machines/p3bf/bx3f1006.awd", + ret = bios_load_linear("roms/machines/p3bf/1008f.004", + 0x000c0000, 262144, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init_ex(model, 2); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x04, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); + pci_register_slot(0x09, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x0B, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0D, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x0E, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x01, PCI_CARD_AGPBRIDGE, 1, 2, 3, 4); + device_add(&i440bx_device); + device_add(&piix4e_device); + device_add(&keyboard_ps2_ami_pci_device); + device_add(&w83977ef_device); + device_add(ics9xxx_get(ICS9250_08)); + device_add(&sst_flash_39sf020_device); + spd_register(SPD_TYPE_SDRAM, 0xF, 256); + device_add(&as99127f_device); /* fans: Chassis, CPU, Power; temperatures: MB, JTPWR, CPU */ + hwm_values.voltages[4] = hwm_values.voltages[5]; /* +12V reading not in line with other boards; appears to be close to the -12V reading */ + + return ret; +} + + +int +machine_at_p3bf_coreboot_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/p3bf/coreboot.rom", + 0x000c0000, 262144, 0); if (bios_only || !ret) return ret; diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 7194ca2d9..76a056286 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -9858,6 +9858,40 @@ const machine_t machines[] = { .device = NULL, .vid_device = NULL }, + { + .name = "[i440BX] ASUS P2B-LS (coreboot)", + .internal_name = "p2bls_coreboot", + .type = MACHINE_TYPE_SLOT1, + .chipset = MACHINE_CHIPSET_INTEL_440BX, + .init = machine_at_p2bls_coreboot_init, + .pad = 0, + .pad0 = 0, + .pad1 = MACHINE_AVAILABLE, + .pad2 = 0, + .cpu = { + .package = CPU_PKG_SLOT1, + .block = CPU_BLOCK_NONE, + .min_bus = 50000000, + .max_bus = 112121212, + .min_voltage = 1300, + .max_voltage = 3500, + .min_multi = 1.5, + .max_multi = 8.0 + }, + .bus_flags = MACHINE_PS2_AGP, + .flags = MACHINE_IDE_DUAL | MACHINE_COREBOOT, + .ram = { + .min = 8192, + .max = 1048576, + .step = 8192 + }, + .nvrmask = 255, + .kbc = KBC_UNKNOWN, + .kbc_p1 = 0, + .gpio = 0, + .device = NULL, + .vid_device = NULL + }, /* Has a Winbond W83977EF Super I/O chip with on-chip KBC with AMIKey-2 KBC firmware. */ { @@ -9894,6 +9928,40 @@ const machine_t machines[] = { .device = NULL, .vid_device = NULL }, + { + .name = "[i440BX] ASUS P3B-F (coreboot)", + .internal_name = "p3bf_coreboot", + .type = MACHINE_TYPE_SLOT1, + .chipset = MACHINE_CHIPSET_INTEL_440BX, + .init = machine_at_p3bf_coreboot_init, + .pad = 0, + .pad0 = 0, + .pad1 = MACHINE_AVAILABLE, + .pad2 = 0, + .cpu = { + .package = CPU_PKG_SLOT1, + .block = CPU_BLOCK_NONE, + .min_bus = 66666667, + .max_bus = 150000000, + .min_voltage = 1300, + .max_voltage = 3500, + .min_multi = 1.5, + .max_multi = 8.0 + }, + .bus_flags = MACHINE_PS2_AGP, + .flags = MACHINE_IDE_DUAL | MACHINE_COREBOOT, + .ram = { + .min = 8192, + .max = 1048576, + .step = 8192 + }, + .nvrmask = 255, + .kbc = KBC_UNKNOWN, + .kbc_p1 = 0, + .gpio = 0, + .device = NULL, + .vid_device = NULL + }, /* Has a Winbond W83977EF Super I/O chip with on-chip KBC with AMIKey-2 KBC firmware. */ { diff --git a/src/mem/mem.c b/src/mem/mem.c index e005772a5..3fd559e46 100644 --- a/src/mem/mem.c +++ b/src/mem/mem.c @@ -23,6 +23,7 @@ #include #include #include +#include #define HAVE_STDARG_H #include <86box/86box.h> #include <86box/version.h> @@ -129,6 +130,10 @@ static mem_mapping_t *write_mapping_bus[MEM_MAPPINGS_NO]; static uint8_t *_mem_exec[MEM_MAPPINGS_NO]; static uint8_t ff_pccache[4] = { 0xff, 0xff, 0xff, 0xff }; static mem_state_t _mem_state[MEM_MAPPINGS_NO]; + +static uint8_t *mtrr_areas[MEM_MAPPINGS_NO]; +static uint8_t mtrr_area_refcounts[MEM_MAPPINGS_NO]; + static uint32_t remap_start_addr; #if (!(defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64)) static size_t ram_size = 0, ram2_size = 0; @@ -783,6 +788,8 @@ readmembl(uint32_t addr) { mem_mapping_t *map; uint64_t a; + uint32_t page; + uint8_t *mtrr; GDBSTUB_MEM_ACCESS(addr, GDBSTUB_MEM_READ, 1); @@ -800,6 +807,11 @@ readmembl(uint32_t addr) } addr = (uint32_t) (addr64 & rammask); + page = (addr >> MEM_GRANULARITY_BITS); + mtrr = mtrr_areas[page]; + if (mtrr) + return mtrr[addr & MEM_GRANULARITY_MASK]; + map = read_mapping[addr >> MEM_GRANULARITY_BITS]; if (map && map->read_b) return map->read_b(addr, map->p); @@ -811,6 +823,8 @@ readmembl(uint32_t addr) void writemembl(uint32_t addr, uint8_t val) { + uint32_t page; + uint8_t *mtrr; mem_mapping_t *map; uint64_t a; @@ -835,6 +849,13 @@ writemembl(uint32_t addr, uint8_t val) } addr = (uint32_t) (addr64 & rammask); + page = (addr >> MEM_GRANULARITY_BITS); + mtrr = mtrr_areas[page]; + if (mtrr) { + mtrr[addr & MEM_GRANULARITY_MASK] = val; + return; + } + map = write_mapping[addr >> MEM_GRANULARITY_BITS]; if (map && map->write_b) map->write_b(addr, val, map->p); @@ -846,6 +867,8 @@ uint8_t readmembl_no_mmut(uint32_t addr, uint32_t a64) { mem_mapping_t *map; + uint32_t page; + uint8_t *mtrr; GDBSTUB_MEM_ACCESS(addr, GDBSTUB_MEM_READ, 1); @@ -859,6 +882,11 @@ readmembl_no_mmut(uint32_t addr, uint32_t a64) } else addr &= rammask; + page = (addr >> MEM_GRANULARITY_BITS); + mtrr = mtrr_areas[page]; + if (mtrr) + return mtrr[addr & MEM_GRANULARITY_MASK]; + map = read_mapping[addr >> MEM_GRANULARITY_BITS]; if (map && map->read_b) return map->read_b(addr, map->p); @@ -872,6 +900,8 @@ void writemembl_no_mmut(uint32_t addr, uint32_t a64, uint8_t val) { mem_mapping_t *map; + uint32_t page; + uint8_t *mtrr; GDBSTUB_MEM_ACCESS(addr, GDBSTUB_MEM_WRITE, 1); @@ -890,6 +920,13 @@ writemembl_no_mmut(uint32_t addr, uint32_t a64, uint8_t val) } else addr &= rammask; + page = (addr >> MEM_GRANULARITY_BITS); + mtrr = mtrr_areas[page]; + if (mtrr) { + mtrr[addr & MEM_GRANULARITY_MASK] = val; + return; + } + map = write_mapping[addr >> MEM_GRANULARITY_BITS]; if (map && map->write_b) map->write_b(addr, val, map->p); @@ -900,6 +937,8 @@ uint16_t readmemwl(uint32_t addr) { mem_mapping_t *map; + uint32_t page; + uint8_t *mtrr; int i; uint64_t a; @@ -944,6 +983,11 @@ readmemwl(uint32_t addr) addr = addr64a[0] & rammask; + page = (addr >> MEM_GRANULARITY_BITS); + mtrr = mtrr_areas[page]; + if (mtrr) + return mtrr[addr & MEM_GRANULARITY_MASK] | ((uint16_t) (mtrr[(addr + 1) & MEM_GRANULARITY_MASK]) << 8); + map = read_mapping[addr >> MEM_GRANULARITY_BITS]; if (map && map->read_w) @@ -961,6 +1005,8 @@ readmemwl(uint32_t addr) void writememwl(uint32_t addr, uint16_t val) { + uint32_t page; + uint8_t *mtrr; mem_mapping_t *map; int i; uint64_t a; @@ -1019,6 +1065,14 @@ writememwl(uint32_t addr, uint16_t val) addr = addr64a[0] & rammask; + page = (addr >> MEM_GRANULARITY_BITS); + mtrr = mtrr_areas[page]; + if (mtrr) { + mtrr[addr & MEM_GRANULARITY_MASK] = val; + mtrr[(addr + 1) & MEM_GRANULARITY_MASK] = val >> 8; + return; + } + map = write_mapping[addr >> MEM_GRANULARITY_BITS]; if (map && map->write_w) { @@ -1038,6 +1092,8 @@ writememwl(uint32_t addr, uint16_t val) uint16_t readmemwl_no_mmut(uint32_t addr, uint32_t *a64) { + uint32_t page; + uint8_t *mtrr; mem_mapping_t *map; GDBSTUB_MEM_ACCESS(addr, GDBSTUB_MEM_READ, 2); @@ -1069,6 +1125,11 @@ readmemwl_no_mmut(uint32_t addr, uint32_t *a64) } else addr &= rammask; + page = (addr >> MEM_GRANULARITY_BITS); + mtrr = mtrr_areas[page]; + if (mtrr) + return mtrr[addr & MEM_GRANULARITY_MASK] | ((uint16_t) (mtrr[(addr + 1) & MEM_GRANULARITY_MASK]) << 8); + map = read_mapping[addr >> MEM_GRANULARITY_BITS]; if (map && map->read_w) @@ -1087,6 +1148,8 @@ readmemwl_no_mmut(uint32_t addr, uint32_t *a64) void writememwl_no_mmut(uint32_t addr, uint32_t *a64, uint16_t val) { + uint32_t page; + uint8_t *mtrr; mem_mapping_t *map; GDBSTUB_MEM_ACCESS(addr, GDBSTUB_MEM_WRITE, 2); @@ -1126,6 +1189,14 @@ writememwl_no_mmut(uint32_t addr, uint32_t *a64, uint16_t val) } else addr &= rammask; + page = (addr >> MEM_GRANULARITY_BITS); + mtrr = mtrr_areas[page]; + if (mtrr) { + mtrr[addr & MEM_GRANULARITY_MASK] = val; + mtrr[(addr + 1) & MEM_GRANULARITY_MASK] = val >> 8; + return; + } + map = write_mapping[addr >> MEM_GRANULARITY_BITS]; if (map && map->write_w) { @@ -1144,6 +1215,8 @@ writememwl_no_mmut(uint32_t addr, uint32_t *a64, uint16_t val) uint32_t readmemll(uint32_t addr) { + uint32_t page; + uint8_t *mtrr; mem_mapping_t *map; int i; uint64_t a = 0x0000000000000000ULL; @@ -1202,6 +1275,11 @@ readmemll(uint32_t addr) addr = addr64a[0] & rammask; + page = (addr >> MEM_GRANULARITY_BITS); + mtrr = mtrr_areas[page]; + if (mtrr) + return mtrr[addr & MEM_GRANULARITY_MASK] | ((uint32_t) (mtrr[(addr + 1) & MEM_GRANULARITY_MASK]) << 8) | ((uint32_t) (mtrr[(addr + 2) & MEM_GRANULARITY_MASK]) << 16) | ((uint32_t) (mtrr[(addr + 3) & MEM_GRANULARITY_MASK]) << 24); + map = read_mapping[addr >> MEM_GRANULARITY_BITS]; if (map && map->read_l) @@ -1224,6 +1302,8 @@ readmemll(uint32_t addr) void writememll(uint32_t addr, uint32_t val) { + uint32_t page; + uint8_t *mtrr; mem_mapping_t *map; int i; uint64_t a = 0x0000000000000000ULL; @@ -1294,6 +1374,16 @@ writememll(uint32_t addr, uint32_t val) addr = addr64a[0] & rammask; + page = (addr >> MEM_GRANULARITY_BITS); + mtrr = mtrr_areas[page]; + if (mtrr) { + mtrr[addr & MEM_GRANULARITY_MASK] = val; + mtrr[(addr + 1) & MEM_GRANULARITY_MASK] = val >> 8; + mtrr[(addr + 2) & MEM_GRANULARITY_MASK] = val >> 16; + mtrr[(addr + 3) & MEM_GRANULARITY_MASK] = val >> 24; + return; + } + map = write_mapping[addr >> MEM_GRANULARITY_BITS]; if (map && map->write_l) { @@ -1320,6 +1410,8 @@ uint32_t readmemll_no_mmut(uint32_t addr, uint32_t *a64) { mem_mapping_t *map; + uint32_t page; + uint8_t *mtrr; GDBSTUB_MEM_ACCESS(addr, GDBSTUB_MEM_READ, 4); @@ -1349,6 +1441,11 @@ readmemll_no_mmut(uint32_t addr, uint32_t *a64) addr = (uint32_t) (a64[0] & rammask); } else addr &= rammask; + + page = (addr >> MEM_GRANULARITY_BITS); + mtrr = mtrr_areas[page]; + if (mtrr) + return mtrr[addr & MEM_GRANULARITY_MASK] | ((uint32_t) (mtrr[(addr + 1) & MEM_GRANULARITY_MASK]) << 8) | ((uint32_t) (mtrr[(addr + 2) & MEM_GRANULARITY_MASK]) << 16) | ((uint32_t) (mtrr[(addr + 3) & MEM_GRANULARITY_MASK]) << 24); map = read_mapping[addr >> MEM_GRANULARITY_BITS]; @@ -1374,6 +1471,8 @@ void writememll_no_mmut(uint32_t addr, uint32_t *a64, uint32_t val) { mem_mapping_t *map; + uint32_t page; + uint8_t *mtrr; GDBSTUB_MEM_ACCESS(addr, GDBSTUB_MEM_WRITE, 4); @@ -1412,6 +1511,16 @@ writememll_no_mmut(uint32_t addr, uint32_t *a64, uint32_t val) } else addr &= rammask; + page = (addr >> MEM_GRANULARITY_BITS); + mtrr = mtrr_areas[page]; + if (mtrr) { + mtrr[addr & MEM_GRANULARITY_MASK] = val; + mtrr[(addr + 1) & MEM_GRANULARITY_MASK] = val >> 8; + mtrr[(addr + 2) & MEM_GRANULARITY_MASK] = val >> 16; + mtrr[(addr + 3) & MEM_GRANULARITY_MASK] = val >> 24; + return; + } + map = write_mapping[addr >> MEM_GRANULARITY_BITS]; if (map && map->write_l) { @@ -1438,6 +1547,8 @@ readmemql(uint32_t addr) { mem_mapping_t *map; int i; + uint32_t page; + uint8_t *mtrr; uint64_t a = 0x0000000000000000ULL; for (i = 0; i < 8; i++) @@ -1493,6 +1604,11 @@ readmemql(uint32_t addr) addr = addr64a[0] & rammask; + page = (addr >> MEM_GRANULARITY_BITS); + mtrr = mtrr_areas[page]; + if (mtrr) + return readmemll(addr) | ((uint64_t)readmemll(addr+4)<<32); + map = read_mapping[addr >> MEM_GRANULARITY_BITS]; if (map && map->read_l) return map->read_l(addr, map->p) | ((uint64_t)map->read_l(addr + 4, map->p) << 32); @@ -1506,6 +1622,8 @@ writememql(uint32_t addr, uint64_t val) { mem_mapping_t *map; int i; + uint32_t page; + uint8_t *mtrr; uint64_t a = 0x0000000000000000ULL; for (i = 0; i < 8; i++) @@ -1572,6 +1690,20 @@ writememql(uint32_t addr, uint64_t val) addr = addr64a[0] & rammask; + page = (addr >> MEM_GRANULARITY_BITS); + mtrr = mtrr_areas[page]; + if (mtrr) { + mtrr[addr & MEM_GRANULARITY_MASK] = val; + mtrr[(addr + 1) & MEM_GRANULARITY_MASK] = val >> 8; + mtrr[(addr + 2) & MEM_GRANULARITY_MASK] = val >> 16; + mtrr[(addr + 3) & MEM_GRANULARITY_MASK] = val >> 24; + mtrr[(addr + 4) & MEM_GRANULARITY_MASK] = val >> 32; + mtrr[(addr + 5) & MEM_GRANULARITY_MASK] = val >> 40; + mtrr[(addr + 6) & MEM_GRANULARITY_MASK] = val >> 48; + mtrr[(addr + 7) & MEM_GRANULARITY_MASK] = val >> 56; + return; + } + map = write_mapping[addr >> MEM_GRANULARITY_BITS]; if (map && map->write_l) { @@ -2717,6 +2849,14 @@ mem_reset(void) memset(pages, 0x00, pages_sz*sizeof(page_t)); + for (c = 0; c < MEM_MAPPINGS_NO; c++) { + if (mtrr_areas[c]) { + free(mtrr_areas[c]); + mtrr_areas[c] = 0; + } + mtrr_area_refcounts[c] = 0; + } + #ifdef USE_NEW_DYNAREC byte_dirty_mask = malloc((mem_size * 1024) / 8); memset(byte_dirty_mask, 0, (mem_size * 1024) / 8); @@ -2821,6 +2961,8 @@ mem_init(void) readlookupp = malloc((1<<20)*sizeof(uint8_t)); writelookup2 = malloc((1<<20)*sizeof(uintptr_t)); writelookupp = malloc((1<<20)*sizeof(uint8_t)); + + memset(mtrr_areas, 0x00, MEM_MAPPINGS_NO*sizeof(uint8_t *)); } @@ -2925,3 +3067,117 @@ mem_a20_recalc(void) mem_a20_state = state; } + + +void +mem_add_mtrr(uint64_t base, uint64_t mask, uint8_t type) +{ + uint64_t size = ((~mask) & 0xffffffff) + 1; + uint64_t page_base, page, addr; + uint8_t *mtrr; + + mem_log("Adding MTRR base=%08llx mask=%08llx size=%08llx type=%d\n", base, mask, size, type); + + if (size > 0x8000) { + mem_log("Ignoring MTRR, size too big\n"); + return; + } + + if (mem_addr_is_ram(base)) { + mem_log("Ignoring MTRR, base is in RAM\n"); + return; + } + + for (page_base = base; page_base < base + size; page_base += MEM_GRANULARITY_SIZE) { + page = (page_base >> MEM_GRANULARITY_BITS); + if (mtrr_areas[page]) { + /* area already allocated, increase refcount and don't allocate it again */ + mtrr_area_refcounts[page]++; + continue; + } + + /* allocate area */ + mtrr = malloc(MEM_GRANULARITY_SIZE); + if (!mtrr) + fatal("Failed to allocate page for MTRR page %08llx (errno=%d)\n", page_base, errno); + + + /* populate area with data from RAM */ + for (addr = 0; addr < MEM_GRANULARITY_SIZE; addr++) { + mtrr[addr] = readmembl(page_base | addr); + } + + /* enable area */ + mtrr_areas[page] = mtrr; + } +} + +void +mem_del_mtrr(uint64_t base, uint64_t mask) +{ + uint64_t size = ((~mask) & 0xffffffff) + 1; + uint64_t page_base, page; + + mem_log("Deleting MTRR base=%08llx mask=%08llx size=%08llx\n", base, mask, size); + + if (size > 0x8000) { + mem_log("Ignoring MTRR, size too big\n"); + return; + } + + if (mem_addr_is_ram(base)) { + mem_log("Ignoring MTRR, base is in RAM\n"); + return; + } + + for (page_base = base; page_base < base + size; page_base += MEM_GRANULARITY_SIZE) { + page = (page_base >> MEM_GRANULARITY_BITS); + if (mtrr_areas[page]) { + /* decrease reference count */ + if (mtrr_area_refcounts[page] > 0) + mtrr_area_refcounts[page]--; + + /* if no references are left, de-allocate area */ + if (mtrr_area_refcounts[page] == 0) { + free(mtrr_areas[page]); + mtrr_areas[page] = 0; + } + } + } +} + + +void +mem_invalidate_mtrr(uint8_t wb) +{ + uint64_t page, page_base, addr; + uint8_t *mtrr; + + mem_log("Invalidating cache (writeback=%d)\n", wb); + for (page = 0; page < MEM_MAPPINGS_NO; page++) { + mtrr = mtrr_areas[page]; + if (mtrr) { + page_base = (page << MEM_GRANULARITY_BITS); + if (!mem_addr_is_ram(page_base)) + continue; /* don't invalidate pages not backed by RAM (hack?) */ + + /* temporarily set area aside */ + mtrr_areas[page] = 0; + + /* write data back to memory if requested */ + if (wb && write_mapping[page]) { /* don't write back to a page which can't be written to */ + for (addr = 0; addr < MEM_GRANULARITY_SIZE; addr++) { + writemembl(page_base | addr, mtrr[addr]); + } + } + + /* re-populate area with data from memory */ + for (addr = 0; addr < MEM_GRANULARITY_SIZE; addr++) { + mtrr[addr] = readmembl(page_base | addr); + } + + /* re-enable area */ + mtrr_areas[page] = mtrr; + } + } +}