So the sets are the big memory area spaces(0-1GB, 1-2GB, 2-3GB and 3-4GB linear memory). Each of those areas(sets) owns 8 entries to store and load entries(struct containing tag(consists of user(CPL being 3 or not), RW(access being a write or not) and linear 4KB block(bits 12-31 of the linear address)), physical address(of the frame) and age(counters are cleared on access and increase over time(update function in paging.c). The lowest age(or first unused TLB entry unused) are used for saving new entries.
https://bitbucket.org/superfury/unipcemu/src/ … ing.c?at=master
In UniPCemu(current commit above), the highest two bits are used for the Set lookup, then looking within the Set(8 entries) for a match.
The Page protection and translation scheme works as follows: (Assuming 80386)
1. A TLB lookup is executed. If it succeeds(hits), the returned address is used and no errors are thrown(TLB lookup means that no further checking is required: U/S and R/W are OK, otherwise it wouldn't be hit(due to TLB only containing valid memory accesses)).
2. If the TLB lookup failed, fetch PDE/PTE from memory, throwing Page Faults when not present. After loading, verify U/S and R/W rights. If not allowed, Page Fault. Otherwise, add entry to TLB and access memory(mappage reads TLB and gives translated address).
Is that behaviour correct? More bits could be added to the tag and/or physical address(data in TLB) for adding security checks(protection). It currently assumes: TLB HIT=Protection OK. Otherwise, fetch PDE/PTE and check as described.