TLB Miss is the core process of memory management in MIPS. In the previous article on MIPS, TLB miss related principles, this article focuses on the Linux kernel code implementation. TLB Refill Initialization
In the kernel boot process, the TLB refill exception is initialized and the corresponding processing interface is set. The main processes are as follows (take r3k as an example):
Start_secondary
per_cpu_trap_init
tlb_init
build_tlb_refill_handler
Build_r3000_tlb_refill_ Handler
The operation of the specific settings handler is performed at Build_r3000_tlb_refill_handler, and the code is as follows:
* * The R3000 TLB handler is simple.
* * * Standard TLB Refill code, relatively simple, with only one page table, with the MIPS manual in the Basic Agreement.
*/static void Build_r3000_tlb_refill_handler (void) {/* page directory */Long PGDC = (long) pgd_current;
U32 *p;
/* Initialize TLB Processing interface * * memset (tlb_handler, 0, sizeof (Tlb_handler));
p = Tlb_handler;
/* Read the virtual address that generated the exception * * UASM_I_MFC0 (&p, K0, c0_badvaddr); Uasm_i_lui (&p, K1, Uasm_rel_hi (PGDC));
/* CP0 Delay * * UASM_I_LW (&p, K1, Uasm_rel_lo (PGDC), K1); UASM_I_SRL (&p, K0, K0, 22);
/* Load Delay * * UASM_I_SLL (&p, K0, K0, 2);
Uasm_i_addu (&p, K1, K1, K0);
/* Read the information from the context Register/* UASM_I_MFC0 (&p, K0, C0_context); UASM_I_LW (&p, K1, 0, K1); /* CP0 Delay * * Uasm_i_andi (&p, K0, K0, 0XFFC);
/* Load Delay * * UASM_I_ADDU (&p, K1, K1, K0);
UASM_I_LW (&p, K0, 0, K1); Uasm_i_nop (&P); /* Read EPC registers, which save the exception return address * * UASM_I_MFC0 (&p, K1, C0_EPC); /* CP0 Delay */* TLBWR instruction, write TLB/UASM_I_TLBWR (&p) According to ENTRYLO0 Register contents (from page table, via context Register index);
/* cp0 delay/* Jump to the exception return address, exit abnormal * * * UASM_I_JR (&p, K1); Uasm_i_rfe (&P); /* Branch delay/* key point: Copy the Tlb_handler (that is, the TLB refill exception handler function) to Ebase * (MIPS is the abnormal allocated physical address space (size is 0x80), with EB
ASE registers point to, in simple cases, * Physical Address 0x0), when the TLB refill exception occurs, the hardware automatically jumps to the ebase corresponding address execution.
* * memcpy (void *) Ebase, Tlb_handler, 0x80);
...
}
It can be seen that the TLB refill exception processing function code, is the kernel dynamic settings, rather than the assembly of static code, due to the MIPS hardware model more, so the operation more flexible.
Also, note that the TLB refill exception handling function entry is located at the fixed physical address: 0x0. General Exception Initialization
During kernel boot, the corresponding exception handling interface for general exception is initialized, the main process is as follows:
Start_kernel
Trap_init
Trap_init complete the exception-related initialization operation, the main code is as follows:
void __init trap_init (void) {//General exception processing interface extern char except_vec3_generic;
... * * Copy the generic exception handlers to their final destination.
* This is overriden later as suitable for a particular * configuration. * * * To copy the general exception processing function (instruction) to the 0x180 (physical address), 0x180 is r4000 above * MIPS CPU in the general exception default entry address, the physical address space size of 0x
80, dedicated * reserved for general exception processing.
* * Set_handler (0x180, &except_vec3_generic, 0x80);
* * Setup Default vectors//x* for exception 0-31 to set the defaults processing interface, general exception corresponding number is 3,tlb refill exception * corresponding to the number 1.
* for (i = 0; I <= i++) set_except_vector (i, handle_reserved);
... * * General exception is the total entry point for all common priority exceptions, where different processing * interfaces are invoked according to the exception code, and here is the corresponding processing interface for setting different exceptions. * Note: The 2nd anomaly code corresponds to the **page fault** exception, that is, the TLB load exception, the processing interface is HANDLE_TLBL/set_except_vector (0, Using_rollback_handler ()? rollback
_handle_int:handle_int);
Set_except_vector (1, HANDLE_TLBM);
Set_except_vector (2, HANDLE_TLBL); Set_exCept_vector (3, handle_tlbs);
Set_except_vector (4, Handle_adel);
Set_except_vector (5, handle_ades);
Set_except_vector (6, Handle_ibe);
Set_except_vector (7, handle_dbe);
/* Set system call Processing interface * * Set_except_vector (8, Handle_sys);
* * According to the different CPU type, set the corresponding general exception processing interface address, corresponding R4, address is * 0x180, other (older) is 0x80. */if (CPU_HAS_VCE)/* Special exception:r4[04]00 uses also the Divec space.
* * Set_handler (0x180, &except_vec3_r4000, 0x100);
else if (Cpu_has_4kex) Set_handler (0x180, &except_vec3_generic, 0x80);
else Set_handler (0x080, &except_vec3_generic, 0x80);
...
}
General Exception Processing
The general exception is processed in the Except_vec3_generic function to assemble the implementation, where the main work is to read the exception type code Exccode and then invoke the corresponding processing interface. The main code is as follows (Genex. S file):
* * General exception vectors for all other CPUs.
*
* is careful when changing this, it has to is at most 128 bytes * to fit into spaces reserved for the
exception h Andler.
* * * * assembly code, eventually copied to the physical address of the 0x180, note that this physical address space is limited in size, the largest 128
* bytes (0x80), so processing can not be too complex.
*/
NESTED (except_vec3_generic, 0, SP)
. Set push
. Set noat
#if r5432_cp0_interrupt_war
MFC0 K0, Cp0_index
#endif
mfc0 K1, cp0_cause //Read the exception type code from the Cp0_cause register
Exccode K1, K1, 0x7c
#ifdef config_64bit
dsll K1, K1, 1
#endif
/
* * According to type code, strip Exception_ The corresponding interface in the handlers, the processing interface in Exception_handlers
is set at Trap_init initialization.
*/
ptr_l K0, Exception_handlers (K1)
Jr K0
. Set pop end
(except_vec3_generic)
TLB Load Exception handling initialization
In the previous general exception initialization process, only the general exception processing portal and different exception code corresponding to the processing interface, but and set up the specific exception handling function, that is, the exception occurred after the specific execution of the code, the initialization is in another process:
Start_secondary
per_cpu_trap_init
tlb_init
build_tlb_refill_handler
build_r3000_tlb_load_ Handler
Implementation in the Build_r3000_tlb_load_handler function, the key code is as follows:
static void Build_r3000_tlb_load_handler (void)
{
u32 *p = handle_tlbl;
const int handle_tlbl_size = HANDLE_TLBL_END-HANDLE_TLBL;
...
/* Initialize *
/memset (HANDLE_TLBL, 0, handle_tlbl_size * sizeof (handle_tlbl[0));
...
* * Write assembly code, equivalent to J Tlb_do_page_fault_0, that is, jump directly to the TLB_DO_PAGE_FAULT_0 place
* execution, that is, call the TLB_DO_PAGE_FAULT_0 function * *
Uasm_i_j (&p, (unsigned long) Tlb_do_page_fault_0 & 0X0FFFFFFF);
Uasm_i_nop (&p);
...
}
TLB Load Exception handling (Page Fault)
As the previous code analysis, the TLB load exception processing interface, in fact, is to call the TLB_DO_PAGE_FAULT_0 function, and then look at this function implementation (assembly code, in Tlbex-fault. S file):
/* Tlb_do_page_fault_0 and tlb_do_page_fault_1 together, through macro control/
macro Tlb_do_page_fault, write
NESTED (tlb_do_page _fault_\write, pt_size, SP)/
* Save context/
save_all
* Read the virtual address of the send exception/
MFC0 A2, Cp0_badvaddr
Kmode
Move A0, SP
reg_s A2, pt_bvaddr (SP)
Li A1, \write
ptr_la ra, ret_from_ Exception/
* Key point: Call the Do_page_fault function * /J Do_page_fault End
(tlb_do_page_fault_\write)
. Endm
The code is very simple, in addition to saving context, such as operations, is called the Do_page_fault function, this is our very familiar page fault standard interface, which will allocate memory, and add page table entries, establish virtual address and physical address mapping relationship. Here is not said, previously written analysis of the document.
Original address: http://happyseeker.github.io/kernel/2016/12/28/mips-TLB-miss-implemented-in-linux.html