int main(void) { unsigned int va; unsigned int stack_addr = (unsigned int) &va & ~(PAGE_SIZE - 1); // Map code & data for (va = 0; va < 0x10000; va += PAGE_SIZE) { add_itlb_mapping(va, va); add_dtlb_mapping(va, va | TLB_WRITABLE); } add_dtlb_mapping(stack_addr, stack_addr | TLB_WRITABLE); add_dtlb_mapping(IO_REGION_BASE, IO_REGION_BASE | TLB_WRITABLE); // Enable MMU and disable supervisor mode in flags register __builtin_nyuzi_write_control_reg(CR_FAULT_HANDLER, general_fault_handler); __builtin_nyuzi_write_control_reg(CR_TLB_MISS_HANDLER, tlb_fault_handler); __builtin_nyuzi_write_control_reg(CR_FLAGS, FLAG_MMU_EN); // This will fault because the thread is in user mode. Then the general // fault handler will read the address to ensure the mapping wasn't inserted. // That should cause a TLB fault. add_dtlb_mapping(data, ((unsigned int)data) | TLB_WRITABLE); // CHECK: general fault 10 // CHECK: TLB fault printf("FAIL: executed instruction\n"); }
int main(void) { unsigned int va; unsigned int stack_addr = (unsigned int) &va & ~(PAGE_SIZE - 1); // Map code & data for (va = 0; va < 0x10000; va += PAGE_SIZE) { add_itlb_mapping(va, va); add_dtlb_mapping(va, va | TLB_WRITABLE); } add_dtlb_mapping(stack_addr, stack_addr | TLB_WRITABLE); add_dtlb_mapping(IO_REGION_BASE, IO_REGION_BASE | TLB_WRITABLE); // A data region. Enter a few bogus mapping first, then the proper // one, which should replace them. add_dtlb_mapping(data_addr, 0x101000 | TLB_WRITABLE); add_dtlb_mapping(data_addr, 0x102000 | TLB_WRITABLE); add_dtlb_mapping(data_addr, 0x103000 | TLB_WRITABLE); add_dtlb_mapping(data_addr, 0x104000 | TLB_WRITABLE); add_dtlb_mapping(data_addr, ((unsigned int) data_addr) | TLB_WRITABLE); // Enable MMU in flags register __builtin_nyuzi_write_control_reg(CR_TLB_MISS_HANDLER, tlb_miss_handler); __builtin_nyuzi_write_control_reg(CR_FLAGS, FLAG_MMU_EN | FLAG_SUPERVISOR_EN); *data_addr = 0x1f6818aa; printf("data value %08x\n", *data_addr); // CHECK: data value 1f6818aa return 0; }
int main(void) { unsigned int va; int asid; unsigned int stack_addr = (unsigned int) &va & ~(PAGE_SIZE - 1); // Map code & data for (va = 0; va < 0x10000; va += PAGE_SIZE) { add_itlb_mapping(va, va | TLB_GLOBAL | TLB_EXECUTABLE | TLB_PRESENT); add_dtlb_mapping(va, va | TLB_WRITABLE | TLB_GLOBAL | TLB_PRESENT); } add_dtlb_mapping(stack_addr, stack_addr | TLB_WRITABLE | TLB_GLOBAL | TLB_PRESENT); add_dtlb_mapping(IO_REGION_BASE, IO_REGION_BASE | TLB_WRITABLE | TLB_GLOBAL | TLB_PRESENT); // Map a private page into address space 1 set_asid(1); add_dtlb_mapping(VADDR1, PADDR1 | TLB_PRESENT); *((unsigned int*) PADDR1) = 0xdeadbeef; // Map a private page into address space 2 set_asid(2); add_dtlb_mapping(VADDR1, PADDR2 | TLB_PRESENT); *((unsigned int*) PADDR2) = 0xabcdefed; // Enable MMU in flags register __builtin_nyuzi_write_control_reg(CR_FAULT_HANDLER, fault_handler); __builtin_nyuzi_write_control_reg(CR_TLB_MISS_HANDLER, fault_handler); __builtin_nyuzi_write_control_reg(CR_FLAGS, FLAG_MMU_EN | FLAG_SUPERVISOR_EN); // Read value from first address space set_asid(1); printf("A1 %08x\n", *((volatile unsigned int*) VADDR1)); // CHECK: A1 deadbeef // Read value from the second address space set_asid(2); printf("A2 %08x\n", *((volatile unsigned int*) VADDR1)); // CHECK: A2 abcdefed return 0; }
int main(void) { unsigned int va; unsigned int stack_addr = (unsigned int) &va & ~(PAGE_SIZE - 1); // Map code & data for (va = 0; va < 0x10000; va += PAGE_SIZE) { add_itlb_mapping(va, va | TLB_GLOBAL); add_dtlb_mapping(va, va | TLB_WRITABLE | TLB_GLOBAL); } add_dtlb_mapping(stack_addr, stack_addr | TLB_WRITABLE); add_dtlb_mapping(data_addr, ((unsigned int)data_addr) | TLB_WRITABLE); // Writable *data_addr2 = 0x12345678; add_dtlb_mapping(data_addr2, data_addr2); // Not writable add_dtlb_mapping(IO_REGION_BASE, IO_REGION_BASE | TLB_WRITABLE); // I/O // Enable MMU in flags register __builtin_nyuzi_write_control_reg(CR_FAULT_HANDLER, fault_handler); __builtin_nyuzi_write_control_reg(CR_TLB_MISS_HANDLER, fault_handler); __builtin_nyuzi_write_control_reg(CR_FLAGS, FLAG_MMU_EN | FLAG_SUPERVISOR_EN); // This should write successfully *data_addr = 0x1f6818aa; printf("data value %08x\n", *data_addr); // CHECK: data value 1f6818aa // Attempt to write to write protected page will fail. *data_addr2 = 0xdeadbeef; // Ensure two things: // - that a fault is raised // - that the value isn't actually written // CHECK: FAULT 7 00101000 // CHECK: data value = 12345678 printf("should_not_be_here\n"); // CHECKN: should_not_be_here return 0; }
int main(void) { unsigned int va; int asid; unsigned int stack_addr = (unsigned int) &va & ~(PAGE_SIZE - 1); // Map code & data for (va = 0; va < 0x10000; va += PAGE_SIZE) { add_itlb_mapping(va, va); add_dtlb_mapping(va, va | TLB_WRITABLE | TLB_GLOBAL); } add_dtlb_mapping(stack_addr, stack_addr | TLB_WRITABLE); add_dtlb_mapping(IO_REGION_BASE, IO_REGION_BASE | TLB_SUPERVISOR | TLB_WRITABLE); // Alias mapping that we will use for test (the normal mapped region is used // to halt the test). add_dtlb_mapping(0x100000, IO_REGION_BASE | TLB_SUPERVISOR | TLB_WRITABLE); __builtin_nyuzi_write_control_reg(CR_FAULT_HANDLER, fault_handler); __builtin_nyuzi_write_control_reg(CR_FLAGS, FLAG_MMU_EN | FLAG_SUPERVISOR_EN); // Can write to page in supervisor mode globaltmp = *((volatile unsigned int*) 0x100000); printf("check1\n"); // CHECK: check1 // Switch to user mode, but leave MMU active switch_to_user_mode(); *((volatile unsigned int*) 0x100000) = 0x12; // CHECK: FAULT 8 00100000 current flags 06 prev flags 02 // XXX no way to verify that the write wasn't sent to external bus }