MyToyOS: Machine Specific Registers

Os processadores Intel possuem mais registradores, além dos de uso geral, controle, debugger, SIMD e testes. Existe um “porrilhão” (grandeza técnica usada para indicar grandes quantidades!) de registradores usados para configurar o processador. Esses registradores são chamados de Machine Specific Registers porque muitos deles são específicos para a arquitetura do processador onde se aplicam.

Um exemplo: O MSR chamado de IA32_APIC_BASE contém, entre outras informações, o endereço básico do APIC local do processador lógico onde este registrador é consultado… O nome IA32_APIC_BASE é apenas um mnemônico, o registrador verdadeiro é identificado por um número que é passado pelo registrador ECX antes da chamada à instrução RDMSR (leitura) ou WRMSR (escrita). Cada um desses MSRs têm 64 bits de tamanho e, portanto, RDMSR retorna o valor no par de registradores EDX:EAX.

As instruções mencionadas só funcionam no ring 0. Caso contrário ela gerará um General Protection Fault, que ocorrerá também se o MSR consultado não existir… Isso quer dizer que você não tem como usar essas instruções num ambiente como Linux ou Windows, no userspace

Como o MS-DOS funciona no modo real e, por definição, executa no ring 0, eis um programinha usando o NASM e o Borland C++ 3.1 para obter o endereço base do Local APIC do processador atual:

bits 16

segment _TEXT public class=CODE align=16 use16

struc rdmsrsrk
.oldbp:   resw 1
.retaddr: resw 1
.msr:     resd 1
.ptr:     resw 1
endstruc

  global _rdmsr
  align 4
_rdmsr:
  push bp
  mov  bp,sp
  mov  ecx,[bp+rdmsrstk.msr]
  rdmsr
  mov  di,[bp+rdmsrstk.ptr]
  mov  [di],eax
  mov  [di+4],edx
  leave
  ret

O programinha em C que usa a rotina acima pode ser assim:

#include <stdio.h>

#define IA32_APIC_BASE 0x1b

struct rdmsr_s { unsigned long a, d; };

extern void rdmsr(unsigned long, struct rdmsr_s *);

void main(void)
{
  struct rdmsr_s r;

  rdmsr(IA32_APIC_BASE, &r);

  // Mostra os bits 31..12 do registrador.
  printf("LAPIC Base Addr = %lx\n",
    (r.a & 0xfffff000UL));
}

Compilando, linkando e executando, temos:

C:\WORK> nasm -f obj -o rdmsr.obj rdmsr.asm
rdmsr.asm:3: warning: segment attributes specified on redeclaration of segment: ignoring

C:\WORK> bcc -3 -ms -otest.obj -c test.c
C:\WORK> tlink \bcc\lib\c0s.obj+test.obj+rdmsr.obj,test.exe,nul,\bcc\lib\cs.lib

C:\WORK> test
LAPIC Base Addr = fee00000

O aviso do NASM indiva que o que é ignorado é o aviso, não a redeclaração do segmento…

A lista completa dos MSRs pode ser obtida no capítulo 35 do volume 3 dos manuais de desenvolvimento de software para as arquiteturas Intel 64 e IA-32 da Intel (link aqui).

Anúncios