VirtualBox

source: vbox/trunk/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegCtxRestore.asm@ 61533

Last change on this file since 61533 was 60774, checked in by vboxsync, 9 years ago

bs3kit: update / iret

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 18.6 KB
Line 
1; $Id: bs3-cmn-RegCtxRestore.asm 60774 2016-05-02 00:04:01Z vboxsync $
2;; @file
3; BS3Kit - Bs3RegCtxRestore.
4;
5
6;
7; Copyright (C) 2007-2016 Oracle Corporation
8;
9; This file is part of VirtualBox Open Source Edition (OSE), as
10; available from http://www.virtualbox.org. This file is free software;
11; you can redistribute it and/or modify it under the terms of the GNU
12; General Public License (GPL) as published by the Free Software
13; Foundation, in version 2 as it comes in the "COPYING" file of the
14; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16;
17; The contents of this file may alternatively be used under the terms
18; of the Common Development and Distribution License Version 1.0
19; (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20; VirtualBox OSE distribution, in which case the provisions of the
21; CDDL are applicable instead of those of the GPL.
22;
23; You may elect to license modified versions of this file under the
24; terms and conditions of either the GPL or the CDDL or both.
25;
26
27%include "bs3kit-template-header.mac"
28
29
30BS3_EXTERN_SYSTEM16 Bs3Gdt
31BS3_EXTERN_DATA16 g_bBs3CurrentMode
32%if TMPL_BITS != 64
33BS3_EXTERN_DATA16 g_uBs3CpuDetected
34%endif
35TMPL_BEGIN_TEXT
36BS3_EXTERN_CMN Bs3Syscall
37BS3_EXTERN_CMN Bs3Panic
38TMPL_BEGIN_TEXT
39
40
41;;
42; Restores the given register context.
43;
44; @param pRegCtx
45; @param fFlags
46; @uses All registers and may trash stack immediately before the resume point.
47;
48; @note Only respects the BS3_MODE_CODE_MASK part of pRegCtx->bMode.
49;
50%if TMPL_BITS == 16
51BS3_PROC_BEGIN_CMN Bs3RegCtxRestore_aborts, BS3_PBC_FAR ; special entry point for when watcom applies __aborts
52BS3_PROC_BEGIN_CMN Bs3RegCtxRestore_aborts, BS3_PBC_NEAR ; special entry point for when watcom applies __aborts
53 CPU 8086
54 xor xAX, xAX
55 push xAX ; fake return address.
56 push xAX
57 jmp _Bs3RegCtxRestore_f16
58%elif TMPL_BITS == 32
59BS3_PROC_BEGIN_CMN Bs3RegCtxRestore_aborts, BS3_PBC_NEAR ; special entry point for when watcom applies __aborts
60 push 0feedfaceh ; fake return address.
61%endif
62BS3_PROC_BEGIN_CMN Bs3RegCtxRestore, BS3_PBC_HYBRID
63 BS3_CALL_CONV_PROLOG 2
64 push xBP
65 mov xBP, xSP
66
67 ;
68 ; If we're not in ring-0, ask the kernel to restore it for us (quicker
69 ; and less problematic if we're in a funny context right now with weird
70 ; CS or SS values).
71 ;
72%if TMPL_BITS == 16
73 cmp byte [BS3_DATA16_WRT(g_bBs3CurrentMode)], BS3_MODE_RM
74 je .in_ring0
75 test byte [BS3_DATA16_WRT(g_bBs3CurrentMode)], BS3_MODE_CODE_V86
76 jnz .do_syscall_restore_ctx
77%endif
78 mov ax, ss
79 test al, 3
80 jz .in_ring0
81
82.do_syscall_restore_ctx:
83%if TMPL_BITS != 16
84.do_syscall_restore_ctx_restore_ds:
85 mov cx, ds
86 mov xSI, [xBP + xCB*2]
87 movzx edx, word [xBP + xCB*3]
88 mov eax, BS3_SYSCALL_RESTORE_CTX
89%else
90 mov si, [bp + xCB + cbCurRetAddr]
91 mov cx, [bp + xCB + cbCurRetAddr + 2]
92 mov dx, [bp + xCB + cbCurRetAddr + sCB]
93 mov ax, BS3_SYSCALL_RESTORE_CTX
94%endif
95 call Bs3Syscall
96 call Bs3Panic
97
98%if TMPL_BITS == 16
99.do_syscall_restore_ctx_restore_ds:
100 push es
101 pop ds
102 jmp .do_syscall_restore_ctx
103%endif
104
105 ;
106 ; Prologue. Loads ES with BS3KIT_GRPNM_DATA16/FLAT (for g_bBs3CurrentMode
107 ; and g_uBs3CpuDetected), DS:xBX with pRegCtx and fFlags into xCX.
108 ;
109.in_ring0:
110%if TMPL_BITS == 16
111 mov ax, BS3_SEL_DATA16
112 mov es, ax
113 lds bx, [bp + xCB + cbCurRetAddr]
114 mov cx, [bp + xCB + cbCurRetAddr + sCB]
115%elif TMPL_BITS == 32
116 mov ax, BS3_SEL_R0_DS32
117 mov ds, ax
118 mov xBX, [xBP + xCB*2]
119 movzx xCX, word [xBP + xCB*3]
120%else
121 mov ax, BS3_SEL_R0_DS64
122 mov ds, ax
123 mov xBX, [xBP + xCB*2]
124 movzx xCX, word [xBP + xCB*3]
125%endif
126
127
128%if TMPL_BITS != 64
129 ; Restoring a 64-bit context is best done from 64-bit code.
130 mov al, [xBX + BS3REGCTX.bMode]
131 test al, BS3_MODE_CODE_64
132 jnz .do_syscall_restore_ctx_restore_ds
133%endif
134
135 ; The remainder must be done with interrupts disabled.
136 cli
137
138 ;
139 ; Update g_bs3CurrentMode.
140 ;
141%if TMPL_BITS == 64
142 mov al, [xBX + BS3REGCTX.bMode]
143%endif
144 and al, BS3_MODE_CODE_MASK
145 mov ah, [BS3_ONLY_16BIT(es:) BS3_DATA16_WRT(g_bBs3CurrentMode)]
146 and ah, ~BS3_MODE_CODE_MASK
147 or al, ah
148 mov [BS3_ONLY_16BIT(es:) BS3_DATA16_WRT(g_bBs3CurrentMode)], al
149
150%if TMPL_BITS == 16
151 ;
152 ; Check what the CPU can do.
153 ;
154 cmp byte [es:BS3_DATA16_WRT(g_uBs3CpuDetected)], BS3CPU_80386
155 jae .restore_full
156
157 ; Do the 80286 specifics first.
158 cmp byte [es:BS3_DATA16_WRT(g_uBs3CpuDetected)], BS3CPU_80286
159 jb .restore_16_bit_ancient
160 CPU 286
161
162 lmsw [bx + BS3REGCTX.cr0]
163 cmp byte [es:BS3_DATA16_WRT(g_bBs3CurrentMode)], BS3_MODE_RM
164 je .restore_16_bit_ancient
165 lldt [bx + BS3REGCTX.ldtr]
166
167 ; TR - complicated because we need to clear the busy bit. ASSUMES GDT.
168 str ax
169 cmp ax, [bx + BS3REGCTX.tr]
170 je .skip_tr_286
171
172 mov di, word [xBX + BS3REGCTX.tr]
173 or di, di ; check for null.
174 jz .load_tr_286
175
176 push ds
177 push BS3_SEL_SYSTEM16
178 pop ds
179 add di, Bs3Gdt wrt BS3SYSTEM16
180 add di, X86DESCGENERIC_BIT_OFF_TYPE / 8
181 and byte [di], ~(X86_SEL_TYPE_SYS_TSS_BUSY_MASK << (X86DESCGENERIC_BIT_OFF_TYPE % 8))
182 pop ds
183
184.load_tr_286:
185 ltr [bx + BS3REGCTX.tr]
186.skip_tr_286:
187
188.restore_16_bit_ancient:
189 CPU 8086
190 ; Some general registers.
191 mov cx, [bx + BS3REGCTX.rcx]
192 mov dx, [bx + BS3REGCTX.rdx]
193
194 ; Do the return frame and final registers (keep short as we're not quite
195 ; NMI safe here if pRegCtx is on the stack).
196 cmp byte [es:BS3_DATA16_WRT(g_bBs3CurrentMode)], BS3_MODE_RM
197 mov di, [bx + BS3REGCTX.rsp]
198 je .restore_16_bit_same_privilege
199 cmp byte [bx + BS3REGCTX.bCpl], 0
200 je .restore_16_bit_same_privilege
201
202 mov ax, [bx + BS3REGCTX.ss]
203 push ax
204 mov ax, [bx + BS3REGCTX.rsp]
205 push ax
206 mov ax, [bx + BS3REGCTX.rflags]
207 push ax
208 mov ax, [bx + BS3REGCTX.cs]
209 push ax
210 mov ax, [bx + BS3REGCTX.rip]
211 push ax
212 mov ax, [bx + BS3REGCTX.ds]
213 push ax
214
215 mov si, [bx + BS3REGCTX.rsi]
216 mov di, [bx + BS3REGCTX.rdi]
217 mov es, [bx + BS3REGCTX.es]
218 mov ax, [bx + BS3REGCTX.rax]
219 mov bp, [bx + BS3REGCTX.rbp] ; restore late for better stacks.
220 mov bx, [bx + BS3REGCTX.rbx]
221
222 pop ds
223 iret
224
225.restore_16_bit_same_privilege:
226 sub di, 2*5 ; iret frame + pop ds
227 mov si, di
228 mov es, [bx + BS3REGCTX.ss] ; ES is target stack segment.
229 cld
230
231 mov ax, [bx + BS3REGCTX.ds]
232 stosw
233 mov ax, [bx + BS3REGCTX.rbp] ; Restore esp as late as possible for better stacks.
234 stosw
235 mov ax, [bx + BS3REGCTX.rip]
236 stosw
237 mov ax, [bx + BS3REGCTX.cs]
238 stosw
239 mov ax, [bx + BS3REGCTX.rflags]
240 stosw
241
242 mov di, [bx + BS3REGCTX.rdi]
243 mov es, [bx + BS3REGCTX.es]
244 mov ax, [bx + BS3REGCTX.rax]
245 mov ss, [bx + BS3REGCTX.ss]
246 mov sp, si
247 mov si, [bx + BS3REGCTX.rsi]
248 mov bx, [bx + BS3REGCTX.rbx]
249
250 pop ds
251 pop bp
252 iret
253
254 CPU 386
255%endif
256
257.restore_full:
258 ;
259 ; 80386 or later.
260 ; For 32-bit and 16-bit versions, we always use 32-bit iret.
261 ;
262
263 ; Restore control registers if they've changed.
264 test cl, BS3TRAPRESUME_F_SKIP_CRX
265 jnz .skip_control_regs
266 test byte [xBX + BS3REGCTX.fbFlags], BS3REG_CTX_F_NO_CR0_IS_MSW | BS3REG_CTX_F_NO_CR2_CR3
267 jnz .skip_control_regs
268
269 test byte [xBX + BS3REGCTX.fbFlags], BS3REG_CTX_F_NO_CR4 ; (old 486s and 386s didn't have CR4)
270 jnz .skip_cr4
271%if TMPL_BITS != 64
272 test word [BS3_ONLY_16BIT(es:) BS3_DATA16_WRT(g_uBs3CpuDetected)], BS3CPU_F_CPUID
273 jz .skip_cr4
274%endif
275 mov sAX, [xBX + BS3REGCTX.cr4]
276 mov sDX, cr4
277 cmp sAX, sDX
278 je .skip_cr4
279 mov cr4, sAX
280.skip_cr4:
281
282 mov sAX, [xBX + BS3REGCTX.cr0]
283 mov sDX, cr0
284 cmp sAX, sDX
285 je .skip_cr0
286 mov cr0, sAX
287.skip_cr0:
288
289 mov sAX, [xBX + BS3REGCTX.cr3]
290 mov sDX, cr3
291 cmp sAX, sDX
292 je .skip_cr3
293 mov cr3, sAX
294.skip_cr3:
295
296 mov sAX, [xBX + BS3REGCTX.cr2]
297 mov sDX, cr2
298 cmp sAX, sDX
299 je .skip_cr2
300 mov cr2, sAX
301.skip_cr2:
302
303 ;
304 ; Restore
305 ;
306%if TMPL_BITS != 64
307 ; We cannot restore ldtr and tr if we're in real-mode.
308 cmp byte [BS3_ONLY_16BIT(es:) BS3_DATA16_WRT(g_bBs3CurrentMode)], BS3_MODE_RM
309 je .skip_control_regs
310%endif
311
312 ; LDTR
313 sldt ax
314 cmp ax, [xBX + BS3REGCTX.ldtr]
315 je .skip_ldtr
316 lldt [xBX + BS3REGCTX.ldtr]
317.skip_ldtr:
318
319 ; TR - complicated because we need to clear the busy bit. ASSUMES GDT.
320 str ax
321 cmp ax, [xBX + BS3REGCTX.tr]
322 je .skip_tr
323
324 movzx edi, word [xBX + BS3REGCTX.tr]
325 or edi, edi ; check for null.
326 jz .load_tr
327
328%if TMPL_BITS == 16
329 push ds
330 push BS3_SEL_SYSTEM16
331 pop ds
332 add xDI, Bs3Gdt wrt BS3SYSTEM16
333%else
334 add xDI, Bs3Gdt wrt FLAT
335%endif
336 add xDI, X86DESCGENERIC_BIT_OFF_TYPE / 8
337 and byte [xDI], ~(X86_SEL_TYPE_SYS_TSS_BUSY_MASK << (X86DESCGENERIC_BIT_OFF_TYPE % 8))
338%if TMPL_BITS == 16
339 pop ds
340%endif
341.load_tr:
342 ltr [xBX + BS3REGCTX.tr]
343.skip_tr:
344
345.skip_control_regs:
346
347
348%if TMPL_BITS == 64
349 ;
350 ; 64-bit returns are simple because ss:rsp are always restored.
351 ;
352 ; A small complication here when returning to a 16-bit stack (only
353 ; applicable to 16-bit and 32-bit code), iret doesn't touch the high
354 ; ESP bits and we can easily later end up with trap handlers
355 ; accessing memory never intended as stack.
356 ;
357 mov rcx, qword [xBX + BS3REGCTX.rsp] ; (also 1st param for conv call below)
358 cmp rcx, 0ffffh
359 ja .iretq_maybe_annoying_16bit_stack
360 cmp rsp, 0ffffh
361 ja .iretq_maybe_annoying_16bit_stack
362.iretq_ok:
363
364 movzx eax, word [xBX + BS3REGCTX.ss]
365 push rax
366 push qword [xBX + BS3REGCTX.rsp]
367 push qword [xBX + BS3REGCTX.rflags]
368 movzx eax, word [xBX + BS3REGCTX.cs]
369 push rax
370 push qword [xBX + BS3REGCTX.rip]
371
372.iretq_restore_regs_and_iret:
373 mov es, [xBX + BS3REGCTX.es]
374 mov fs, [xBX + BS3REGCTX.fs]
375 mov gs, [xBX + BS3REGCTX.gs]
376 mov rax, [xBX + BS3REGCTX.rax]
377 mov rdx, [xBX + BS3REGCTX.rdx]
378 mov rcx, [xBX + BS3REGCTX.rcx]
379 mov rsi, [xBX + BS3REGCTX.rsi]
380 mov rdi, [xBX + BS3REGCTX.rdi]
381 mov r8, [xBX + BS3REGCTX.r8]
382 mov r9, [xBX + BS3REGCTX.r9]
383 mov r10, [xBX + BS3REGCTX.r10]
384 mov r11, [xBX + BS3REGCTX.r11]
385 mov r12, [xBX + BS3REGCTX.r12]
386 mov r13, [xBX + BS3REGCTX.r13]
387 mov r14, [xBX + BS3REGCTX.r14]
388 mov r15, [xBX + BS3REGCTX.r15]
389 mov rbp, [xBX + BS3REGCTX.rbp] ; restore late for better stacks.
390 mov ds, [xBX + BS3REGCTX.ds]
391 mov rbx, [xBX + BS3REGCTX.rbx]
392 iretq
393
394.iretq_maybe_annoying_16bit_stack:
395 movzx edx, word [xBX + BS3REGCTX.ss] ; (also 2nd param for conv call below)
396 lar eax, dx
397 jnz .iretq_ok
398 test eax, X86LAR_F_D | X86LAR_F_L
399 jnz .iretq_ok ; Returning to a big of long SS needs not extra work.
400
401 lar eax, word [xBX + BS3REGCTX.cs]
402 jnz .iretq_ok
403 test eax, X86LAR_F_L
404 jnz .iretq_ok ; It doesn't matter when returning to 64-bit code.
405
406 ; Convert ss:sp to a flat address.
407 BS3_EXTERN_CMN Bs3SelFar32ToFlat32NoClobber
408 call Bs3SelFar32ToFlat32NoClobber
409 mov rdi, rax
410
411 ; 2nd return frame (32-bit, same CPL).
412 mov eax, [xBX + BS3REGCTX.rflags]
413 mov [rdi - 4], eax
414 movzx eax, word [xBX + BS3REGCTX.cs]
415 mov [rdi - 8], eax
416 mov eax, [xBX + BS3REGCTX.rip]
417 mov [rdi - 12], eax
418 mov ecx, [xBX + BS3REGCTX.rsp]
419 sub cx, 12
420 mov [rdi - 16], ecx
421
422 ; 1st return frame.
423 movzx eax, word [xBX + BS3REGCTX.ss]
424 push rax ; new 16-bit SS
425 sub cx, 4
426 push rcx ; new esp
427 mov rax, [xBX + BS3REGCTX.rflags]
428 and rax, ~(X86_EFL_NT | X86_EFL_TF)
429 push rax ; rflags
430 AssertCompile(BS3_SEL_RING_SHIFT == 8)
431 mov eax, BS3_SEL_R0_CS32
432 add ah, [xBX + BS3REGCTX.bCpl]
433 or al, [xBX + BS3REGCTX.bCpl]
434 push rax ; 32-bit CS
435 push .iretq_pop_real_esp_and_iret_again wrt FLAT
436 jmp .iretq_restore_regs_and_iret
437
438 BS3_SET_BITS 32
439.iretq_pop_real_esp_and_iret_again:
440 pop esp
441 iretd
442 BS3_SET_BITS 64
443
444%else
445 ;
446 ; 32-bit/16-bit is more complicated as we have three different iret frames.
447 ;
448 mov al, [BS3_ONLY_16BIT(es:) BS3_DATA16_WRT(g_bBs3CurrentMode)]
449 cmp al, BS3_MODE_RM
450 je .iretd_same_cpl_rm
451
452 test dword [xBX + BS3REGCTX.rflags], X86_EFL_VM
453 jnz .restore_v8086
454
455 cmp byte [xBX + BS3REGCTX.bCpl], 0
456 je .iretd_same_cpl
457
458 ;
459 ; IRETD to different CPL. Frame includes ss:esp.
460 ;
461.iretd_different_cpl:
462 or eax, 0ffffffffh ; poison unused parts of segment pushes
463 mov ax, [xBX + BS3REGCTX.ss]
464 push eax
465 push dword [xBX + BS3REGCTX.rsp]
466 push dword [xBX + BS3REGCTX.rflags]
467 mov ax, [xBX + BS3REGCTX.cs]
468 push eax
469 push dword [xBX + BS3REGCTX.rip]
470 push dword [xBX + BS3REGCTX.rbp] ; Restore esp as late as possible for better stacks.
471 mov ax, [xBX + BS3REGCTX.ds]
472 push xAX
473
474 mov es, [xBX + BS3REGCTX.es]
475 mov fs, [xBX + BS3REGCTX.fs]
476 mov gs, [xBX + BS3REGCTX.gs]
477 mov eax, [xBX + BS3REGCTX.rax]
478 mov edx, [xBX + BS3REGCTX.rdx]
479 mov ecx, [xBX + BS3REGCTX.rcx]
480 mov esi, [xBX + BS3REGCTX.rsi]
481 %if TMPL_BITS == 16 ; if SS is 16-bit, we will not be able to restore the high word.
482;; @todo 16-bit stack will also mess us up in 32-bit code, so this needs fixing (see 64-bit above).
483 mov edi, [xBX + BS3REGCTX.rsp]
484 mov di, sp
485 mov esp, edi
486 %endif
487 mov edi, [xBX + BS3REGCTX.rdi]
488 mov ebx, [xBX + BS3REGCTX.rbx]
489
490 pop ds
491 pop ebp
492 iretd
493
494 ;
495 ; IRETD to same CPL (includes real mode).
496 ;
497.iretd_same_cpl_rm:
498 ; Use STOSD/ES:EDI to create the frame.
499 mov es, [xBX + BS3REGCTX.ss]
500 mov esi, [xBX + BS3REGCTX.rsp]
501 sub esi, 5*4
502 movzx edi, si
503 jmp .es_edi_is_pointing_to_return_frame_location
504
505.iretd_same_cpl:
506 ; Use STOSD/ES:EDI to create the frame.
507 mov es, [xBX + BS3REGCTX.ss]
508 mov edi, [xBX + BS3REGCTX.rsp]
509 sub edi, 5*4
510
511 ; Which part of the stack pointer is actually used depends on the SS.D/B bit.
512 lar eax, [xBX + BS3REGCTX.ss]
513 jnz .using_32_bit_stack_pointer
514 test eax, X86LAR_F_D
515 jnz .using_32_bit_stack_pointer
516.using_16_bit_stack_pointer:
517 mov esi, edi ; save rsp for later.
518 movzx edi, di
519 jmp .es_edi_is_pointing_to_return_frame_location
520.using_32_bit_stack_pointer:
521 mov esi, edi
522.es_edi_is_pointing_to_return_frame_location:
523 cld
524 mov ax, [xBX + BS3REGCTX.ds]
525 o32 stosd
526 mov eax, [xBX + BS3REGCTX.rbp] ; Restore esp as late as possible for better stacks.
527 o32 stosd
528 mov eax, [xBX + BS3REGCTX.rip]
529 o32 stosd
530 mov ax, [xBX + BS3REGCTX.cs]
531 o32 stosd
532 mov eax, [xBX + BS3REGCTX.rflags]
533 o32 stosd
534
535 mov es, [xBX + BS3REGCTX.es]
536 mov fs, [xBX + BS3REGCTX.fs]
537 mov gs, [xBX + BS3REGCTX.gs]
538 mov eax, [xBX + BS3REGCTX.rax]
539 mov edx, [xBX + BS3REGCTX.rdx]
540 mov ecx, [xBX + BS3REGCTX.rcx]
541 mov edi, [xBX + BS3REGCTX.rdi]
542 mov ebp, [xBX + BS3REGCTX.rbp] ; restore late for better stacks.
543
544 mov ss, [xBX + BS3REGCTX.ss]
545 mov esp, esi
546 mov esi, [xBX + BS3REGCTX.rsi]
547 mov ebx, [xBX + BS3REGCTX.rbx]
548
549 o32 pop ds
550 pop ebp
551 iretd
552
553 ;
554 ; IRETD to v8086 mode. Frame includes ss:esp and the 4 data segment registers.
555 ;
556.restore_v8086:
557 or eax, 0ffffffffh ; poison unused parts of segment pushes
558 mov eax, [xBX + BS3REGCTX.gs]
559 push eax
560 mov eax, [xBX + BS3REGCTX.fs]
561 push eax
562 mov eax, [xBX + BS3REGCTX.ds]
563 push eax
564 mov eax, [xBX + BS3REGCTX.es]
565 push eax
566 mov eax, [xBX + BS3REGCTX.ss]
567 push eax
568 push dword [xBX + BS3REGCTX.rsp]
569 push dword [xBX + BS3REGCTX.rflags]
570 mov ax, [xBX + BS3REGCTX.cs]
571 push eax
572 push dword [xBX + BS3REGCTX.rip]
573
574 mov eax, [xBX + BS3REGCTX.rax]
575 mov edx, [xBX + BS3REGCTX.rdx]
576 mov ecx, [xBX + BS3REGCTX.rcx]
577 mov esi, [xBX + BS3REGCTX.rsi]
578 mov edi, [xBX + BS3REGCTX.rdi]
579 mov ebp, [xBX + BS3REGCTX.rbp] ; restore late for better stacks.
580 mov ebx, [xBX + BS3REGCTX.rbx]
581
582 iretd
583%endif
584BS3_PROC_END_CMN Bs3RegCtxRestore
585
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette