Replaced the mmutranslate functions in mem.c with slightly altered versions of Sarah's, should increase performance even slightly more.
This commit is contained in:
193
src/mem.c
193
src/mem.c
@@ -196,124 +196,95 @@ int pctrans=0;
|
|||||||
|
|
||||||
extern uint32_t testr[9];
|
extern uint32_t testr[9];
|
||||||
|
|
||||||
static __inline__ int mem_cpl3_check(void)
|
#define rammap(x) ((uint32_t *)(_mem_exec[(x) >> 14]))[((x) >> 2) & 0xfff]
|
||||||
{
|
|
||||||
if ((CPL == 3) && !cpl_override)
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static __inline__ void mmu_page_fault(uint32_t addr, uint32_t error_code)
|
|
||||||
{
|
|
||||||
cr2 = addr;
|
|
||||||
cpu_state.abrt = ABRT_PF;
|
|
||||||
abrt_error = error_code;
|
|
||||||
}
|
|
||||||
|
|
||||||
static __inline__ int mmu_page_fault_check(uint32_t addr, int rw, uint32_t flags, int pde, int is_abrt)
|
|
||||||
{
|
|
||||||
uint8_t error_code = 0;
|
|
||||||
|
|
||||||
uint8_t is_page_fault = 0;
|
|
||||||
|
|
||||||
if (CPL == 3) error_code = 4; /* If the page fault has occurred at CPL 3, this should be set. */
|
|
||||||
if (rw) error_code |= 2; /* If the page has occurred during a write, this should be set. */
|
|
||||||
|
|
||||||
/* Apparently, this check should not be done on PSE. */
|
|
||||||
if (!(flags & 1))
|
|
||||||
is_page_fault = 1;
|
|
||||||
else
|
|
||||||
error_code |= 1; /* If the page is present, the error must indicate that it is. */
|
|
||||||
|
|
||||||
if (!(flags & 4) && mem_cpl3_check()) {
|
|
||||||
/* The user/supervisor check needs to be checked for the table as well, *before* checking it for the page. */
|
|
||||||
is_page_fault = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Only check the write-protect flag if this is a page directory entry. */
|
|
||||||
if (pde && rw && !(flags & 2) && ((cr0 & WP_FLAG) || mem_cpl3_check()))
|
|
||||||
is_page_fault = 1;
|
|
||||||
|
|
||||||
if (is_page_fault) {
|
|
||||||
if (is_abrt)
|
|
||||||
mmu_page_fault(addr, error_code);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define PAGE_DIRTY_AND_ACCESSED 0x60
|
|
||||||
#define PAGE_DIRTY 0x40
|
|
||||||
#define PAGE_ACCESSED 0x20
|
|
||||||
|
|
||||||
/* rw means 0 = read, 1 = write */
|
|
||||||
uint32_t mmutranslate(uint32_t addr, int rw, int is_abrt)
|
|
||||||
{
|
|
||||||
/* Mask out the lower 12 bits. */
|
|
||||||
uint32_t dir_base = 0;
|
|
||||||
|
|
||||||
uint32_t table_addr = 0;
|
|
||||||
uint32_t page_addr = 0;
|
|
||||||
|
|
||||||
uint32_t table_flags = 0;
|
|
||||||
uint32_t page_flags = 0;
|
|
||||||
|
|
||||||
if (cpu_state.abrt)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
dir_base = cr3 & ~0xfff;
|
|
||||||
table_addr = dir_base + ((addr >> 20) & 0xffc);
|
|
||||||
|
|
||||||
/* First check the flags of the page directory entry. */
|
|
||||||
table_flags = *(uint32_t *) &_mem_exec[table_addr >> 14][table_addr & 0x3fff];
|
|
||||||
|
|
||||||
if ((table_flags & 0x80) && (cr4 & CR4_PSE)) {
|
|
||||||
/* Do a PDE-style page fault check. */
|
|
||||||
if (mmu_page_fault_check(addr, rw, table_flags & 7, 1, is_abrt) == -1)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
/* Since PSE is not enabled, there is no page table, so we do a slightly modified skip to the end. */
|
|
||||||
if (is_abrt) {
|
|
||||||
mmu_perm = table_flags & 4;
|
|
||||||
*(uint32_t *) &_mem_exec[table_addr >> 14][table_addr & 0x3fff] = table_flags | (rw ? PAGE_DIRTY_AND_ACCESSED : PAGE_ACCESSED);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (table_flags & ~0x3FFFFF) + (addr & 0x3FFFFF);
|
|
||||||
} else {
|
|
||||||
/* Do a non-PDE-style page fault check. */
|
|
||||||
if (mmu_page_fault_check(addr, rw, table_flags & 7, 0, is_abrt) == -1)
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
page_addr = table_flags & ~0xfff;
|
|
||||||
page_addr += ((addr >> 10) & 0xffc);
|
|
||||||
|
|
||||||
/* Then check the flags of the page table entry. */
|
|
||||||
page_flags = *(uint32_t *) &_mem_exec[page_addr >> 14][page_addr & 0x3fff];
|
|
||||||
|
|
||||||
if (mmu_page_fault_check(addr, rw, page_flags & 7, 1, is_abrt) == -1)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (is_abrt) {
|
|
||||||
mmu_perm = page_flags & 4;
|
|
||||||
*(uint32_t *) &_mem_exec[table_addr >> 14][table_addr & 0x3fff] = table_flags | PAGE_ACCESSED;
|
|
||||||
*(uint32_t *) &_mem_exec[page_addr >> 14][page_addr & 0x3fff] = page_flags | (rw ? PAGE_DIRTY_AND_ACCESSED : PAGE_ACCESSED);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (page_flags & ~0xFFF) + (addr & 0xFFF);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t mmutranslatereal(uint32_t addr, int rw)
|
uint32_t mmutranslatereal(uint32_t addr, int rw)
|
||||||
{
|
{
|
||||||
return mmutranslate(addr, rw, 1);
|
uint32_t addr2;
|
||||||
|
uint32_t temp,temp2,temp3;
|
||||||
|
|
||||||
|
if (cpu_state.abrt)
|
||||||
|
return -1;
|
||||||
|
addr2 = ((cr3 & ~0xfff) + ((addr >> 20) & 0xffc));
|
||||||
|
temp=temp2=rammap(addr2);
|
||||||
|
if (!(temp&1)) {
|
||||||
|
cr2=addr;
|
||||||
|
temp&=1;
|
||||||
|
if (CPL==3) temp|=4;
|
||||||
|
if (rw) temp|=2;
|
||||||
|
cpu_state.abrt = ABRT_PF;
|
||||||
|
abrt_error = temp;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((temp & 0x80) && (cr4 & CR4_PSE)) {
|
||||||
|
/*4MB page*/
|
||||||
|
if ((CPL == 3 && !(temp & 4) && !cpl_override) || (rw && !(temp & 2) && ((CPL == 3 && !cpl_override) || cr0 & WP_FLAG))) {
|
||||||
|
cr2 = addr;
|
||||||
|
temp &= 1;
|
||||||
|
if (CPL == 3)
|
||||||
|
temp |= 4;
|
||||||
|
if (rw)
|
||||||
|
temp |= 2;
|
||||||
|
cpu_state.abrt = ABRT_PF;
|
||||||
|
abrt_error = temp;
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
mmu_perm = temp & 4;
|
||||||
|
rammap(addr2) |= 0x20;
|
||||||
|
|
||||||
|
return (temp & ~0x3fffff) + (addr & 0x3fffff);
|
||||||
|
}
|
||||||
|
|
||||||
|
temp=rammap((temp&~0xFFF)+((addr>>10)&0xFFC));
|
||||||
|
temp3=temp&temp2;
|
||||||
|
if (!(temp&1) || (CPL==3 && !(temp3&4) && !cpl_override) || (rw && !(temp3&2) && ((CPL == 3 && !cpl_override) || cr0&WP_FLAG))) {
|
||||||
|
cr2=addr;
|
||||||
|
temp&=1;
|
||||||
|
if (CPL==3) temp|=4;
|
||||||
|
if (rw) temp|=2;
|
||||||
|
cpu_state.abrt = ABRT_PF;
|
||||||
|
abrt_error = temp;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
mmu_perm=temp&4;
|
||||||
|
rammap(addr2)|=0x20;
|
||||||
|
rammap((temp2&~0xFFF)+((addr>>10)&0xFFC))|=(rw?0x60:0x20);
|
||||||
|
|
||||||
|
return (temp&~0xFFF)+(addr&0xFFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t mmutranslate_noabrt(uint32_t addr, int rw)
|
uint32_t mmutranslate_noabrt(uint32_t addr, int rw)
|
||||||
{
|
{
|
||||||
return mmutranslate(addr, rw, 0);
|
uint32_t addr2;
|
||||||
|
uint32_t temp,temp2,temp3;
|
||||||
|
|
||||||
|
if (cpu_state.abrt)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
addr2 = ((cr3 & ~0xfff) + ((addr >> 20) & 0xffc));
|
||||||
|
temp=temp2=rammap(addr2);
|
||||||
|
|
||||||
|
if (!(temp&1))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if ((temp & 0x80) && (cr4 & CR4_PSE)) {
|
||||||
|
/*4MB page*/
|
||||||
|
if ((CPL == 3 && !(temp & 4) && !cpl_override) || (rw && !(temp & 2) && (CPL == 3 || cr0 & WP_FLAG)))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return (temp & ~0x3fffff) + (addr & 0x3fffff);
|
||||||
|
}
|
||||||
|
|
||||||
|
temp=rammap((temp&~0xFFF)+((addr>>10)&0xFFC));
|
||||||
|
temp3=temp&temp2;
|
||||||
|
|
||||||
|
if (!(temp&1) || (CPL==3 && !(temp3&4) && !cpl_override) || (rw && !(temp3&2) && (CPL==3 || cr0&WP_FLAG)))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return (temp&~0xFFF)+(addr&0xFFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
void mmu_invalidate(uint32_t addr)
|
void mmu_invalidate(uint32_t addr)
|
||||||
|
|||||||
Reference in New Issue
Block a user