Hi all, this should be a short summary what we discussed on IRC.
The following MMU operations are considered for now: - TLB UPDATE - TLB INVALIDATE (one entry) - TLB FLUSH (invalidate all entries for the given TLB) These operations work either on the ITLB or the DTLB. To communicate these opertions to the MMU two new CSRs are introduced: TLBVADDR and TLBPADDR. Additionally, one new processor status register PSW (processor status word) is addded, which contains the bits IE, ITLB, DTLB and USR. All bits have an Exxx and Bxxx equivalent (eg. there are ITLB, EITLB and BITLB bits), which follow the IE semantics (see LM32 reference manual). IE, EIE and BIE are shadowed from the IE register. Therefore, legacy programs can still use the IE register, while new MMU aware programs use the PSW register. TLB operations Because TLB UPDATE is the only operation where a physical address is needed. Writing to TLBPADDR implicitly issues an TLB UPDATE (of course TLBVADDR have to be set before). To choose between ITLB and DTLB, the lowest bit of TLBVADDR is used. Any other operation are encoded into the free bits in TLBVADDR. Thus this operations can be performed atomically, except for the UPDATE, which should run from the TLB miss handler with MMU turned off (or the user must take special care to avoid any exception, eg. turn off interrupts, make sure there is no ITLB miss [don't cross page boundaries] and no DTLB miss [no load between setting VADDR and PADDR]). The same TLB miss exception vector is used for both ITLB and DTLB. On a TLB miss exception TLBVADDR is preloaded with the correct TLB operation (that is either ITLB_NOP or DTLB_NOP, see below) and the virtual address there is no mapping for. There may be other exception vectors for page permission fault or user mode exceptions. The ITLB and DTLB bits are cleared when an exception occurs and saved to EITLB/BITLB rsp. EDTLB/BDTLB. Kernel/User mode In kernel mode all CPU operations are unrestricted. In user mode (USR bit is set) writing CSRs, reading (some) CSRs are prohibited. Exceptions clears the USR bit and saves the old state in EUSR or BUSR. Thus the only way to return to kernel mode is via scall opcode, interrupt or any other exception. The following is a proposal for the CSR ids and its bits: enum { ... CSR_PSW = 0x1d, CSR_TLBVADDR = 0x1e, CSR_TLBPADDR = 0x1f, }; enum { PSW_IE = (1<<0), PSW_EIE = (1<<1), PSW_BIE = (1<<2), PSW_ITLB = (1<<4), PSW_EITLB = (1<<5), PSW_BITLB = (1<<6), PSW_DTLB = (1<<7), PSW_EDTLB = (1<<8), PSW_BDTLB = (1<<9), PSW_USR = (1<<10), PSW_EUSR = (1<<11), PSW_BUSR = (1<<12), }; /* commands, encoded into the lowest bits in TLBVADDR */ enum { ITLB_NOP = 0x00, /* used for UPDATE */ DTLB_NOP = 0x01, /* used for UPDATE */ ITLB_INVALIDATE = 0x02, DTLB_INVALIDATE = 0x03, ITLB_FLUSH = 0x04, /* actual vaddr bits are ignored */ DTLB_FLUSH = 0x05, /* actual vaddr bits are ignored */ }; /* TLB properties, encoded into lowest bits in TLBPADDR */ enum { TLB_VALID = (1<<0), /* set by hardware on update/invalidate */ TLB_R = (1<<1), TLB_W = (1<<2), TLB_X = (1<<3), }; TBD: reading the entries back for debugging purposes: - writing TLBVADDR, with special command? maybe ITLB/DTLB_NOP is sufficient. - reading TLBVADDR -> gets vfn - reading TLBPADDR -> get pfn + permissions + valid bit TBD: if the kernel is executing with MMU enabled, but MMU is turned off on exception, how do we handle interrupt/tlb miss handling, eg. how do we access the kernels page table? TBD: introduce MMU bit in CFG2 CSR. -- Michael _______________________________________________ http://lists.milkymist.org/listinfo.cgi/devel-milkymist.org IRC: #milkymist@Freenode