Subversion Repositories Kolibri OS

Rev

Rev 7132 | Rev 7733 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                              ;;
  3. ;; Copyright (C) KolibriOS team 2004-2015. All rights reserved. ;;
  4. ;; Distributed under terms of the GNU General Public License    ;;
  5. ;;                                                              ;;
  6. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  7.  
  8. $Revision: 7136 $
  9.  
  10. align 4
  11. proc mem_test
  12. ; if we have BIOS with fn E820, skip the test
  13.         cmp     dword [BOOT_LO.memmap_block_cnt], 0
  14.         jnz     .ret
  15.  
  16.         mov     eax, cr0
  17.         and     eax, not (CR0_CD+CR0_NW)
  18.         or      eax, CR0_CD       ;disable caching
  19.         mov     cr0, eax
  20.         wbinvd                    ;invalidate cache
  21.  
  22.         xor     edi, edi
  23.         mov     ebx, 'TEST'
  24. @@:
  25.         add     edi, 0x100000
  26.         xchg    ebx, dword [edi]
  27.         cmp     dword [edi], 'TEST'
  28.         xchg    ebx, dword [edi]
  29.         je      @b
  30.  
  31.         and     eax, not (CR0_CD+CR0_NW) ;enable caching
  32.         mov     cr0, eax
  33.         inc     dword [BOOT_LO.memmap_block_cnt]
  34.         xor     eax, eax
  35.         mov     [BOOT_LO.memmap_blocks + e820entry.addr.lo], eax
  36.         mov     [BOOT_LO.memmap_blocks + e820entry.addr.hi], eax
  37.         mov     [BOOT_LO.memmap_blocks + e820entry.size.lo], edi
  38.         mov     [BOOT_LO.memmap_blocks + e820entry.size.hi], eax
  39.         inc     eax
  40.         mov     [BOOT_LO.memmap_blocks + e820entry.type], eax
  41. .ret:
  42.         ret
  43. endp
  44.  
  45. align 4
  46. proc init_mem
  47. ; calculate maximum allocatable address and number of allocatable pages
  48.         mov     edi, BOOT_LO.memmap_blocks
  49.         mov     ecx, [edi-4]
  50.         xor     esi, esi; esi will hold total amount of memory
  51.         xor     edx, edx; edx will hold maximum allocatable address
  52. .calcmax:
  53. ; round all to pages
  54.         mov     eax, [edi]
  55.         cmp     [edi+16], byte 1
  56.         jne     .unusable
  57.  
  58.         test    eax, 0xFFF
  59.         jz      @f
  60.         neg     eax
  61.         and     eax, 0xFFF
  62.         add     [edi], eax
  63.         adc     dword [edi+4], 0
  64.         sub     [edi+8], eax
  65.         sbb     dword [edi+12], 0
  66.         jc      .unusable
  67. @@:
  68.         and     dword [edi+8], not 0xFFF
  69.         jz      .unusable
  70. ; ignore memory after 4 Gb
  71.         cmp     dword [edi+4], 0
  72.         jnz     .unusable
  73.         mov     eax, [edi]
  74.         cmp     dword [edi+12], 0
  75.         jnz     .overflow
  76.         add     eax, [edi+8]
  77.         jnc     @f
  78. .overflow:
  79.         mov     eax, 0xFFFFF000
  80. @@:
  81.         cmp     edx, eax
  82.         jae     @f
  83.         mov     edx, eax
  84. @@:
  85.         sub     eax, [edi]
  86.         mov     [edi+8], eax
  87.         add     esi, eax
  88.         jmp     .usable
  89. .unusable:
  90. ;        and     dword [edi+8], 0
  91. .usable:
  92.         add     edi, 20
  93.         loop    .calcmax
  94. .calculated:
  95.         mov     [MEM_AMOUNT-OS_BASE], esi
  96.         mov     [pg_data.mem_amount-OS_BASE], esi
  97.         shr     esi, 12
  98.         mov     [pg_data.pages_count-OS_BASE], esi
  99.  
  100.         shr     edx, 12
  101.         add     edx, 31
  102.         and     edx, not 31
  103.         shr     edx, 3
  104.         mov     [pg_data.pagemap_size-OS_BASE], edx
  105.  
  106.         add     edx, (sys_pgmap-OS_BASE)+4095
  107.         and     edx, not 4095
  108.         mov     [tmp_page_tabs], edx
  109.  
  110.         mov     edx, esi
  111.         and     edx, -1024
  112.         cmp     edx, (OS_BASE/4096)
  113.         jbe     @F
  114.         mov     edx, (OS_BASE/4096)
  115.         jmp     .set
  116. @@:
  117.         cmp     edx, (HEAP_BASE-OS_BASE+HEAP_MIN_SIZE)/4096
  118.         jae     .set
  119.         mov     edx, (HEAP_BASE-OS_BASE+HEAP_MIN_SIZE)/4096
  120. .set:
  121.         mov     [pg_data.kernel_pages-OS_BASE], edx
  122.         shr     edx, 10
  123.         mov     [pg_data.kernel_tables-OS_BASE], edx
  124.  
  125.         xor     eax, eax
  126.         mov     edi, sys_proc-OS_BASE
  127.         mov     ecx, 8192/4
  128.         cld
  129.         rep stosd
  130.  
  131.         mov     edx, (sys_proc-OS_BASE+PROC.pdt_0)+ 0x800; (OS_BASE shr 20)
  132.         bt      [cpu_caps-OS_BASE], CAPS_PSE
  133.         jnc     .no_PSE
  134.  
  135.         mov     ebx, cr4
  136.         or      ebx, CR4_PSE
  137.         mov     eax, PDE_LARGE+PG_SWR
  138.         mov     cr4, ebx
  139.         dec     [pg_data.kernel_tables-OS_BASE]
  140.  
  141.         mov     [edx], eax
  142.         add     edx, 4
  143.  
  144.         mov     edi, [tmp_page_tabs]
  145.         jmp     .map_kernel_heap        ; new kernel fits to the first 4Mb - nothing to do with ".map_low"
  146. .no_PSE:
  147.         mov     eax, PG_SWR
  148.         mov     ecx, [tmp_page_tabs]
  149.         shr     ecx, 12
  150. .map_low:
  151.         mov     edi, [tmp_page_tabs]
  152. @@:                                   ;
  153.         stosd
  154.         add     eax, 0x1000
  155.         dec     ecx
  156.         jnz     @B
  157.  
  158. .map_kernel_heap:
  159.         mov     ecx, [pg_data.kernel_tables-OS_BASE]
  160.         shl     ecx, 10
  161.         xor     eax, eax
  162.         rep stosd
  163.  
  164.         mov     ecx, [pg_data.kernel_tables-OS_BASE]
  165.         mov     eax, [tmp_page_tabs]
  166.         or      eax, PG_SWR
  167.         mov     edi, edx
  168.  
  169. .map_kernel_tabs:
  170.         stosd
  171.         add     eax, 0x1000
  172.         dec     ecx
  173.         jnz     .map_kernel_tabs
  174.  
  175.         mov     dword [sys_proc-OS_BASE+PROC.pdt_0+(page_tabs shr 20)], sys_proc+PROC.pdt_0+PG_SWR-OS_BASE
  176.  
  177.         mov     edi, (sys_proc+PROC.pdt_0-OS_BASE)
  178.         lea     esi, [edi+(OS_BASE shr 20)]
  179.         movsd
  180.         movsd
  181.         ret
  182. endp
  183.  
  184. align 4
  185. proc init_page_map
  186. ; mark all memory as unavailable
  187.         mov     edi, sys_pgmap-OS_BASE
  188.         mov     ecx, [pg_data.pagemap_size-OS_BASE]
  189.         shr     ecx, 2
  190.         xor     eax, eax
  191.         cld
  192.         rep stosd
  193.  
  194. ; scan through memory map and mark free areas as available
  195.         mov     ebx, BOOT_LO.memmap_blocks
  196.         mov     edx, [ebx-4]
  197. .scanmap:
  198.         cmp     [ebx+16], byte 1
  199.         jne     .next
  200.  
  201.         mov     ecx, [ebx+8]
  202.         shr     ecx, 12; ecx = number of pages
  203.         jz      .next
  204.         mov     edi, [ebx]
  205.         shr     edi, 12; edi = first page
  206.         mov     eax, edi
  207.         shr     edi, 5
  208.         shl     edi, 2
  209.         add     edi, sys_pgmap-OS_BASE
  210.         and     eax, 31
  211.         jz      .startok
  212.         add     ecx, eax
  213.         sub     ecx, 32
  214.         jbe     .onedword
  215.         push    ecx
  216.         mov     ecx, eax
  217.         or      eax, -1
  218.         shl     eax, cl
  219.         or      [edi], eax
  220.         add     edi, 4
  221.         pop     ecx
  222. .startok:
  223.         push    ecx
  224.         shr     ecx, 5
  225.         or      eax, -1
  226.         rep stosd
  227.         pop     ecx
  228.         and     ecx, 31
  229.         neg     eax
  230.         shl     eax, cl
  231.         dec     eax
  232.         or      [edi], eax
  233.         jmp     .next
  234. .onedword:
  235.         add     ecx, 32
  236.         sub     ecx, eax
  237. @@:
  238.         bts     [edi], eax
  239.         inc     eax
  240.         loop    @b
  241. .next:
  242.         add     ebx, 20
  243.         dec     edx
  244.         jnz     .scanmap
  245.  
  246. ; mark kernel memory as allocated (unavailable)
  247.         mov     ecx, [tmp_page_tabs]
  248.         mov     edx, [pg_data.pages_count-OS_BASE]
  249.         shr     ecx, 12
  250.         add     ecx, [pg_data.kernel_tables-OS_BASE]
  251.         sub     edx, ecx
  252.         mov     [pg_data.pages_free-OS_BASE], edx
  253.  
  254.         mov     edi, sys_pgmap-OS_BASE
  255.         mov     ebx, ecx
  256.         shr     ecx, 5
  257.         xor     eax, eax
  258.         rep stosd
  259.  
  260.         not     eax
  261.         mov     ecx, ebx
  262.         and     ecx, 31
  263.         shl     eax, cl
  264.         and     [edi], eax
  265.         add     edi, OS_BASE
  266.         mov     [page_start-OS_BASE], edi;
  267.  
  268.         mov     ebx, sys_pgmap
  269.         add     ebx, [pg_data.pagemap_size-OS_BASE]
  270.         mov     [page_end-OS_BASE], ebx
  271.  
  272.         ret
  273. endp
  274.  
  275. align 4
  276.  
  277. init_BIOS32:
  278.         mov     edi, 0xE0000
  279. .pcibios_nxt:
  280.         cmp     dword[edi], '_32_'; "magic" word
  281.         je      .BIOS32_found
  282. .pcibios_nxt2:
  283.         add     edi, 0x10
  284.         cmp     edi, 0xFFFF0
  285.         je      .BIOS32_not_found
  286.         jmp     .pcibios_nxt
  287. .BIOS32_found:                  ; magic word found, check control summ
  288.  
  289.         movzx   ecx, byte[edi + 9]
  290.         shl     ecx, 4
  291.         mov     esi, edi
  292.         xor     eax, eax
  293.         cld      ; paranoia
  294. @@:
  295.         lodsb
  296.         add     ah, al
  297.         loop    @b
  298.         jnz     .pcibios_nxt2; control summ must be zero
  299.     ; BIOS32 service found !
  300.         mov     ebp, [edi + 4]
  301.         mov     [bios32_entry], ebp
  302.     ; check PCI BIOS present
  303.         mov     eax, '$PCI'
  304.         xor     ebx, ebx
  305.         push    cs  ; special for 'ret far' from  BIOS
  306.         call    ebp
  307.         test    al, al
  308.         jnz     .PCI_BIOS32_not_found
  309.  
  310.  ; здесь создаются дискрипторы для PCI BIOS
  311.  
  312.         add     ebx, OS_BASE
  313.         dec     ecx
  314.         mov     [(pci_code_32-OS_BASE)], cx   ;limit 0-15
  315.         mov     [(pci_data_32-OS_BASE)], cx   ;limit 0-15
  316.  
  317.         mov     [(pci_code_32-OS_BASE)+2], bx ;base  0-15
  318.         mov     [(pci_data_32-OS_BASE)+2], bx ;base  0-15
  319.  
  320.         shr     ebx, 16
  321.         mov     [(pci_code_32-OS_BASE)+4], bl ;base  16-23
  322.         mov     [(pci_data_32-OS_BASE)+4], bl ;base  16-23
  323.  
  324.         shr     ecx, 16
  325.         and     cl, 0x0F
  326.         mov     ch, bh
  327.         add     cx, D32
  328.         mov     [(pci_code_32-OS_BASE)+6], cx ;lim   16-19 &
  329.         mov     [(pci_data_32-OS_BASE)+6], cx ;base  24-31
  330.  
  331.         mov     [(pci_bios_entry-OS_BASE)], edx
  332.          ; jmp .end
  333. .PCI_BIOS32_not_found:
  334.         ; здесь должна заполнятся pci_emu_dat
  335. .BIOS32_not_found:
  336. .end:
  337.         ret
  338.  
  339. align 4
  340. proc test_cpu
  341.            locals
  342.               cpu_type   dd ?
  343.            endl
  344.  
  345.         xor     eax, eax
  346.         mov     [cpu_type], eax
  347.         mov     [cpu_caps-OS_BASE], eax
  348.         mov     [cpu_caps+4-OS_BASE], eax
  349.         mov     [cpu_phys_addr_width-OS_BASE], 32
  350.  
  351.         pushfd
  352.         pop     eax
  353.         mov     ecx, eax
  354.         xor     eax, EFLAGS_AC
  355.         push    eax
  356.         popfd
  357.         pushfd
  358.         pop     eax
  359.         xor     eax, ecx
  360.         mov     [cpu_type], CPU_386
  361.         jz      .end_cpuid
  362.         push    ecx
  363.         popfd
  364.  
  365.         mov     [cpu_type], CPU_486
  366.         mov     eax, ecx
  367.         xor     eax, EFLAGS_ID
  368.         push    eax
  369.         popfd
  370.         pushfd
  371.         pop     eax
  372.         xor     eax, ecx
  373.         je      .end_cpuid
  374.  
  375.         xor     eax, eax
  376.         cpuid
  377.  
  378.         mov     [cpu_vendor-OS_BASE], ebx
  379.         mov     [cpu_vendor+4-OS_BASE], edx
  380.         mov     [cpu_vendor+8-OS_BASE], ecx
  381.  
  382.         cmp     eax, 1
  383.         jl      .end_cpuid
  384.         mov     eax, 1
  385.         cpuid
  386.         mov     [cpu_sign-OS_BASE], eax
  387.         mov     [cpu_info-OS_BASE], ebx
  388.         mov     [cpu_caps-OS_BASE], edx
  389.         mov     [cpu_caps+4-OS_BASE], ecx
  390.  
  391.         bt      edx, CAPS_PAE
  392.         jnc     @f
  393.         mov     [cpu_phys_addr_width-OS_BASE], 36
  394. @@:
  395.         mov     eax, 0x80000000
  396.         cpuid
  397.         cmp     eax, 0x80000008
  398.         jb      @f
  399.         mov     eax, 0x80000008
  400.         cpuid
  401.         mov     [cpu_phys_addr_width-OS_BASE], al
  402. @@:
  403.  
  404.         mov     eax, [cpu_sign-OS_BASE]
  405.         shr     eax, 8
  406.         and     eax, 0x0f
  407.         ret
  408. .end_cpuid:
  409.         mov     eax, [cpu_type]
  410.         ret
  411. endp
  412.  
  413. iglobal
  414. align 4
  415. acpi_lapic_base   dd 0xfee00000   ; default local apic base
  416. endg
  417.  
  418. uglobal
  419. align 4
  420. acpi_rsdp         rd 1
  421. acpi_rsdt         rd 1
  422. acpi_madt         rd 1
  423.  
  424. acpi_dev_data     rd 1
  425. acpi_dev_size     rd 1
  426.  
  427. acpi_rsdt_base    rd 1
  428. acpi_fadt_base    rd 1
  429. acpi_dsdt_base    rd 1
  430. acpi_dsdt_size    rd 1
  431. acpi_madt_base    rd 1
  432. acpi_ioapic_base  rd 1
  433. acpi_hpet_base    rd 1
  434. hpet_base         rd 1
  435. hpet_period       rd 1
  436. hpet_timers       rd 1
  437. hpet_tsc_start    rd 2
  438. cpu_count         rd 1
  439. smpt              rd 16
  440. endg
  441.  
  442. ACPI_HI_RSDP_WINDOW_START  = 0x000E0000
  443. ACPI_HI_RSDP_WINDOW_END    = 0x00100000
  444. ACPI_RSDP_CHECKSUM_LENGTH  = 20
  445.  
  446. ACPI_HPET_SIGN             = 'HPET'
  447. ACPI_MADT_SIGN             = 'APIC'
  448. ACPI_FADT_SIGN             = 'FACP'
  449.  
  450.  
  451. acpi_locate:
  452.         push    ebx
  453.         push    edi
  454.  
  455. if defined UEFI
  456.         ; UEFI loader knows where RSDP is
  457.         mov     ebx, [BOOT_LO.acpi_rsdp]
  458.         test    ebx, ebx
  459.         jz      .done
  460.         call    .check
  461. else
  462.         movzx   ebx, word [0x40E]
  463.         shl     ebx, 4
  464.         lea     ecx, [ebx+1024]
  465.         call    .check
  466.  
  467.         test    ebx, ebx
  468.         jz      @F
  469.         jmp     .done
  470.  
  471. @@:
  472.         mov     ebx, ACPI_HI_RSDP_WINDOW_START
  473.         mov     edi, ACPI_HI_RSDP_WINDOW_END
  474.         call    .check
  475. end if
  476. .done:
  477.         mov     eax, ebx
  478.         pop     edi
  479.         pop     ebx
  480.         ret
  481.  
  482. .check:
  483.         cmp     [ebx], dword 'RSD '
  484.         jne     .next
  485.         cmp     [ebx+4], dword 'PTR '
  486.         jne     .next
  487.  
  488.         mov     edx, ebx
  489.         mov     ecx, ACPI_RSDP_CHECKSUM_LENGTH
  490.         xor     eax, eax
  491. .sum:
  492.         add     al, [edx]
  493.         inc     edx
  494.         loop    .sum
  495.  
  496.         test    al, al
  497.         jnz     .next
  498.         ret
  499. .next:
  500.         add     ebx, 16
  501.         cmp     ebx, edi
  502.         jb      .check
  503.         xor     ebx, ebx
  504.         ret
  505.  
  506. align 4
  507. rsdt_find:           ;ecx= rsdt edx= SIG
  508.         push    ebx
  509.         push    esi
  510.  
  511.         lea     ebx, [ecx+36]
  512.         mov     esi, [ecx+4]
  513.         add     esi, ecx
  514. align 4
  515. .next:
  516.         mov     eax, [ebx]
  517.         cmp     [eax], edx
  518.         je      .done
  519.  
  520.         add     ebx, 4
  521.         cmp     ebx, esi
  522.         jb      .next
  523.  
  524.         xor     eax, eax
  525.         pop     esi
  526.         pop     ebx
  527.         ret
  528.  
  529. .done:
  530.         mov     eax, [ebx]
  531.         pop     esi
  532.         pop     ebx
  533.         ret
  534.  
  535. align 4
  536. check_acpi:
  537.  
  538.         call    acpi_locate
  539.         test    eax, eax
  540.         jz      .done
  541.  
  542.         mov     [acpi_rsdp-OS_BASE], eax
  543.         mov     ecx, [eax+16]
  544.         mov     edx, ACPI_FADT_SIGN
  545.         mov     [acpi_rsdt_base-OS_BASE], ecx
  546.         call    rsdt_find
  547.         mov     [acpi_fadt_base-OS_BASE], eax
  548.         test    eax, eax
  549.         jz      @f
  550.  
  551.         mov     eax, [eax+40]
  552.         mov     [acpi_dsdt_base-OS_BASE], eax
  553.         mov     eax, [eax+4]
  554.         mov     [acpi_dsdt_size-OS_BASE], eax
  555. @@:
  556.         mov     edx, ACPI_HPET_SIGN
  557.         mov     ecx, [acpi_rsdt_base-OS_BASE]
  558.         call    rsdt_find
  559.         test    eax, eax
  560.         jz      @F
  561.  
  562.         mov     [acpi_hpet_base-OS_BASE], eax
  563.         mov     eax, [eax+44]
  564.         mov     [hpet_base-OS_BASE], eax
  565. @@:
  566.         mov     edx, ACPI_MADT_SIGN
  567.         mov     ecx, [acpi_rsdt_base-OS_BASE]
  568.         call    rsdt_find
  569.         test    eax, eax
  570.         jz      .done
  571.  
  572.         mov     [acpi_madt_base-OS_BASE], eax
  573.         mov     ecx, [eax+36]
  574.         mov     [acpi_lapic_base-OS_BASE], ecx
  575.  
  576.         mov     edi, smpt-OS_BASE
  577.         mov     ebx, [ecx+0x20]
  578.         shr     ebx, 24              ; read APIC ID
  579.  
  580.         mov     [edi], ebx           ; bootstrap always first
  581.         inc     [cpu_count-OS_BASE]
  582.         add     edi, 4
  583.  
  584.         lea     edx, [eax+44]
  585.         mov     ecx, [eax+4]
  586.         add     ecx, eax
  587. .check:
  588.         mov     eax, [edx]
  589.         cmp     al, 0
  590.         jne     .io_apic
  591.  
  592.         shr     eax, 24              ; get APIC ID
  593.         cmp     eax, ebx             ; skip self
  594.         je      .next
  595.  
  596.         test    [edx+4], byte 1      ; is enabled ?
  597.         jz      .next
  598.  
  599.         cmp     [cpu_count-OS_BASE], 16
  600.         jae     .next
  601.  
  602.         stosd                        ; store APIC ID
  603.         inc     [cpu_count-OS_BASE]
  604. .next:
  605.         mov     eax, [edx]
  606.         movzx   eax, ah
  607.         add     edx, eax
  608.         cmp     edx, ecx
  609.         jb      .check
  610. .done:
  611.         ret
  612.  
  613. .io_apic:
  614.         cmp     al, 1
  615.         jne     .next
  616.  
  617.         mov     eax, [edx+4]
  618.         mov     [acpi_ioapic_base-OS_BASE], eax
  619.         jmp     .next
  620.  
  621. HPET_PERIOD             = 0x0004
  622. HPET_CFG_ENABLE         = 0x0001
  623. HPET_CFG                = 0x0010
  624. HPET_COUNTER            = 0x00f0
  625. HPET_T0_CFG             = 0x0100
  626.  
  627. HPET_TN_LEVEL           = 0x0002
  628. HPET_TN_ENABLE          = 0x0004
  629. HPET_TN_FSB             = 0x4000
  630.  
  631. align 4
  632. init_hpet:
  633.         mov     ebx, [hpet_base-OS_BASE]
  634.         test    ebx, ebx
  635.         jz      .done
  636.  
  637.         mov     eax, [ebx]
  638.         and     ah, 0x1F
  639.         inc     ah
  640.         movzx   eax, ah
  641.         mov     [hpet_timers-OS_BASE], eax
  642.         mov     ecx, eax
  643.  
  644.         mov     eax, [ebx+HPET_PERIOD]
  645.         xor     edx, edx
  646.         shld    edx, eax, 10
  647.         shl     eax, 10
  648.         mov     esi, 1000000
  649.         div     esi
  650.         mov     [hpet_period-OS_BASE], eax
  651.  
  652.         mov     esi, [ebx+HPET_CFG]
  653.         and     esi, not HPET_CFG_ENABLE
  654.         mov     [ebx+HPET_CFG], esi             ;stop main counter
  655.  
  656.         lea     edx, [ebx+HPET_T0_CFG]
  657. @@:
  658.         jcxz    @F
  659.         mov     eax, [edx]
  660.         and     eax, not (HPET_TN_ENABLE+HPET_TN_LEVEL+HPET_TN_FSB)
  661.         mov     [edx], eax
  662.         add     edx, 0x20
  663.         dec     ecx
  664.         jmp     @B
  665. @@:
  666.         mov     [ebx+HPET_COUNTER], ecx         ;reset main counter
  667.         mov     [ebx+HPET_COUNTER+4], ecx
  668.  
  669.         or      esi, HPET_CFG_ENABLE
  670.         mov     [ebx+HPET_CFG], esi             ;and start again
  671.  
  672. .done:
  673.         rdtsc
  674.         mov     [hpet_tsc_start-OS_BASE], eax
  675.         mov     [hpet_tsc_start+4-OS_BASE], edx
  676.  
  677.         ret
  678.  
  679.  
  680.  
  681.  
  682.