cos2000v2/lib/cpu.c

338 lines
10 KiB
C
Raw Permalink Normal View History

/*******************************************************************************/
/* COS2000 - Compatible Operating System - LGPL v3 - Hordé Nicolas */
/* */
#include "types.h"
#include "cpu.h"
#include "memory.h"
#include "string.h"
2018-09-01 15:11:54 +02:00
#include "asm.h"
#include "gdt.h"
2018-12-26 00:54:19 +01:00
#include "process.h"
/* Technologies supportées */
static u8 *msg[] = {
"mmx",
"mmx2",
"sse",
"sse2",
"sse3",
"fpu",
"3dNow!",
"3dNow Extended!",
"HyperThreading",
"apic",
"64bits",
"syscall",
"msr",
"sse4a",
"vmx",
"sse41",
"sse42",
"apic2"
};
static u8 space[] = " ";
/******************************************************************************/
/* Affiche une erreur CPU et fige l'ordinateur */
2018-12-26 00:54:19 +01:00
void cpuerror(const u8 * src, const regs * dump, bool returnto)
{
2018-12-26 00:54:19 +01:00
process *aprocess=findcurrentprocess();
if (!aprocess->iskernel && !returnto)
{
printf("\033[31m*** ERREUR CPU, KILLING PROCESS %u : %s *** \r\n", aprocess->pid, src);
deleteprocess(aprocess->pid);
}
else
printf("\033[31m*** ERREUR CPU : %s *** \r\n", src);
if (dump != NULL)
show_cpu(dump);
print("<Appuyer une touche pour continuer>\033[0m\r\n");
sti();
waitascii();
if (!returnto)
{
print("Retour en force au SHELL\r\n");
initselectors(getinitretry());
}
}
/******************************************************************************/
/* Annule les FLAGs CPU */
bool cansetflag(u32 flag)
{
u32 r1, r2;
asm("pushfl\n" "popl %0\n" "movl %0, %1\n" "xorl %2, %0\n" "pushl %0\n" "popfl\n" "pushfl\n" "popl %0\n" "pushl %1\n" "popfl\n": "=&r"(r1), "=&r"(r2):"ir"(flag));
return ((r1 ^ r2) & flag) != 0;
}
/******************************************************************************/
/* Lance l'instruction CPUID */
void cpuid(u32 op, u32 * eax, u32 * ebx, u32 * ecx, u32 * edx)
{
asm("cpuid": "=a"(*eax), "=b"(*ebx), "=c"(*ecx), "=d"(*edx): "a"(op):"cc");
}
/******************************************************************************/
/* Retourne les informations sur le CPU dans une structure cpuinfo */
u8 getcpuinfos(cpuinfo * proc)
{
u32 i, maxfunction, maxextended, unused, regeax, regebx,
regecx, regedx;
bool *boolean;
if (!cansetflag(0x00040000))
return 1; /*386 processor - no cpuid */
if (!cansetflag(0x00200000))
return 2; /*486 processor with no cpuid */
cpuid(0, &maxfunction, &unused, &unused, &unused);
maxfunction &= 0xffff;
cpuid(0x80000000, &maxextended, &unused, &unused, &unused);
maxextended &= 0xffff;
if (maxfunction >= 1)
{
cpuid(1, &regeax, &regebx, &regecx, &regedx);
proc->stepping = (regeax & 0x0000000F);
proc->models = ((regeax >> 4) & 0x0000000F);
proc->family = ((regeax >> 8) & 0x0000000F);
proc->types = ((regeax >> 12) & 0x00000003);
proc->emodels = ((regeax >> 16) & 0x0000000F);
proc->efamily = ((regeax >> 20) & 0x000000FF);
proc->brandid = (regeax & 0xF);
proc->linesize = ((regeax >> 8) & 0xF);
proc->count = ((regeax >> 16) & 0xF);
proc->apicid = ((regeax >> 24) & 0xF);
proc->mmx = ((regedx >> 23) & 0x00000001);
proc->sse = ((regedx >> 25) & 0x00000001);
proc->sse2 = ((regedx >> 26) & 0x00000001);
proc->sse3 = (regecx & 0x00000001);
proc->fpu = (regedx & 0x00000001);
proc->htt = ((regedx >> 28) & 0x00000001);
proc->vmx = ((regecx >> 5) & 0x00000001);
proc->sse41 = ((regecx >> 19) & 0x00000001);
proc->sse42 = ((regecx >> 20) & 0x00000001);
proc->apic2 = ((regecx >> 21) & 0x00000001);
}
if (maxextended >= 1)
{
cpuid(0x80000001, &regeax, &regebx, &regecx, &regedx);
proc->mmx2 = ((regedx >> 22) & 0x00000001);
proc->apic = ((regedx >> 9) & 0x00000001);
proc->now3d = ((regedx >> 30) & 0x00000001);
proc->now3d2 = ((regedx >> 31) & 0x00000001);
proc->bits64 = ((regedx >> 29) & 0x00000001);
proc->syscall = ((regedx >> 11) & 0x00000001);
proc->msr = ((regedx >> 5) & 0x00000001);
proc->sse4a = ((regecx >> 6) & 0x00000001);
}
if (maxextended >= 4)
{
int i;
for (i = 0; i < 3; i++)
{
cpuid(0x80000002 + i, &regeax, &regebx, &regecx,
&regedx);
memcpy(&regeax, &proc->detectedname[0 + i * 16], 4,
1);
memcpy(&regebx, &proc->detectedname[4 + i * 16], 4,
1);
memcpy(&regecx, &proc->detectedname[8 + i * 16], 4,
1);
memcpy(&regedx, &proc->detectedname[12 + i * 16],
4, 1);
}
}
boolean = &proc->mmx;
i = 0;
proc->techs[0] = '\000';
for (i = 0; i < sizeof(msg); i++)
if (*(boolean++) == 1)
{
strcat(msg[i], &proc->techs);
strcat(space, &proc->techs);
}
return 0;
}
/******************************************************************************/
/* Affiche les registres CPU */
void show_lightcpu(regs * stack)
{
u32 i;
printf("\33[0mEAX=%Y EBX=%Y ECX=%Y EDX=%Y\r\n", stack->eax,
stack->ebx, stack->ecx, stack->edx);
printf("ESI=%Y EDI=%Y ESP=%Y EBP=%Y\r\n", stack->esi, stack->edi,
stack->esp, stack->ebp);
printf("EIP=%Y EFL=%Y [%c%c%c%c%c%c%c%c%c]\r\n", stack->eip,
stack->eflags, (stack->eflags & (1 << 11)) ? 'O' : '-',
(stack->eflags & (1 << 10)) ? 'D' : '-',
(stack->eflags & (1 << 9)) ? 'I' : '-',
(stack->eflags & (1 << 8)) ? 'T' : '-',
(stack->eflags & (1 << 7)) ? 'S' : '-',
(stack->eflags & (1 << 6)) ? 'Z' : '-',
(stack->eflags & (1 << 4)) ? 'A' : '-',
(stack->eflags & (1 << 2)) ? 'P' : '-',
(stack->eflags & (1 << 0)) ? 'C' : '-');
printf("CS =%hY DS =%hY SS =%hY ES =%hY FS =%hY GS =%hY\r\n",
stack->cs, stack->ds, stack->ss, stack->es, stack->fs,
stack->gs);
printf("CR0=%Y CR2=%Y CR3=%Y CR4=%Y\r\n\r\n\r\n", stack->cr0,
stack->cr2, stack->cr3, stack->cr4);
u8 *size;
u8 *pointer;
for (i = 20; i < 50; i++)
{
pointer = stack->eip - i;
size = pointer;
size += 50;
while (pointer < size)
{
pointer += disasm(pointer, NULL, false);
if (pointer == stack->eip)
break;
}
if (pointer == stack->eip)
break;
}
if (pointer == stack->eip)
pointer = stack->eip - i;
else
pointer = stack->eip;
size = pointer;
size += 50;
while (pointer < size)
{
if (pointer == stack->eip)
print("\33[41m\33[1m");
else
print("\33[40m\33[0m");
pointer += disasm(pointer, NULL, true);
}
printf("\33[0m\r\n\r\n\r\nSTACK\r\n");
if (abs(KERNEL_STACK_ADDR - stack->esp) > 0x10000)
printf("Pile invalide !");
else
{
i = 0;
for (u32 * pointer = stack->esp;
pointer < KERNEL_STACK_ADDR; pointer++)
{
if (i > 0 && i % 10 == 0)
print("\033[10A");
if (i >= 10)
print("\033[25C");
printf("+%d:%Y - %Y\r\n", i++, pointer,
(u32) (*pointer));
}
for (u32 j = 0; j < 10 - (i % 10); j++)
print("\033[01B");
}
}
/******************************************************************************/
/* Affiche les registres CPU */
void show_cpu(regs * stack)
{
printf("EAX=%Y EBX=%Y ECX=%Y EDX=%Y\r\n", stack->eax, stack->ebx,
stack->ecx, stack->edx);
printf("ESI=%Y EDI=%Y ESP=%Y EBP=%Y\r\n", stack->esi, stack->edi,
stack->esp, stack->ebp);
printf("EIP=%Y EFL=%Y [%c%c%c%c%c%c%c%c%c]\r\n", stack->eip,
stack->eflags, (stack->eflags & (1 << 11)) ? 'O' : '-',
(stack->eflags & (1 << 10)) ? 'D' : '-',
(stack->eflags & (1 << 9)) ? 'I' : '-',
(stack->eflags & (1 << 8)) ? 'T' : '-',
(stack->eflags & (1 << 7)) ? 'S' : '-',
(stack->eflags & (1 << 6)) ? 'Z' : '-',
(stack->eflags & (1 << 4)) ? 'A' : '-',
(stack->eflags & (1 << 2)) ? 'P' : '-',
(stack->eflags & (1 << 0)) ? 'C' : '-');
printf("CS =%hY %Y %Y DPL=%d %cS%d [%c%c%c] %h ub\r\n", stack->cs,
getdesbase(stack->cs), getdeslimit(stack->cs),
getdesdpl(stack->cs), getdestype(stack->cs),
getdessize(stack->cs), getdesbit3(stack->cs),
getdesbit2(stack->cs), getdesbit1(stack->cs),
getdesalign(stack->cs));
printf("DS =%hY %Y %Y DPL=%d %cS%d [%c%c%c] %h ub\r\n", stack->ds,
getdesbase(stack->ds), getdeslimit(stack->ds),
getdesdpl(stack->ds), getdestype(stack->ds),
getdessize(stack->ds), getdesbit3(stack->ds),
getdesbit2(stack->ds), getdesbit1(stack->ds),
getdesalign(stack->ds));
printf("SS =%hY %Y %Y DPL=%d %cS%d [%c%c%c] %h ub\r\n", stack->ss,
getdesbase(stack->ss), getdeslimit(stack->ss),
getdesdpl(stack->ss), getdestype(stack->ss),
getdessize(stack->ss), getdesbit3(stack->ss),
getdesbit2(stack->ss), getdesbit1(stack->ss),
getdesalign(stack->ss));
printf("ES =%hY %Y %Y DPL=%d %cS%d [%c%c%c] %h ub\r\n", stack->es,
getdesbase(stack->es), getdeslimit(stack->es),
getdesdpl(stack->es), getdestype(stack->es),
getdessize(stack->es), getdesbit3(stack->es),
getdesbit2(stack->es), getdesbit1(stack->es),
getdesalign(stack->es));
printf("FS =%hY %Y %Y DPL=%d %cS%d [%c%c%c] %h ub\r\n", stack->fs,
getdesbase(stack->fs), getdeslimit(stack->fs),
getdesdpl(stack->fs), getdestype(stack->fs),
getdessize(stack->fs), getdesbit3(stack->fs),
getdesbit2(stack->fs), getdesbit1(stack->fs),
getdesalign(stack->fs));
printf("GS =%hY %Y %Y DPL=%d %cS%d [%c%c%c] %h ub\r\n", stack->gs,
getdesbase(stack->gs), getdeslimit(stack->gs),
getdesdpl(stack->gs), getdestype(stack->gs),
getdessize(stack->gs), getdesbit3(stack->gs),
getdesbit2(stack->gs), getdesbit1(stack->gs),
getdesalign(stack->gs));
u32 tss;
str(tss);
printf("TR =%hY %Y %Y DPL=%d %cS%d [%c%c%c] %h ub\r\n", stack->gs,
getdesbase(tss), getdeslimit(tss), getdesdpl(tss),
getdestype(tss), getdessize(tss), getdesbit3(tss),
getdesbit2(tss), getdesbit1(tss), getdesalign(tss));
struct gdtr gdtreg;
sgdt(gdtreg);
printf("GDT= %Y %Y\r\n", gdtreg.base, gdtreg.limite);
struct idtr idtreg;
sidt(idtreg);
printf("IDT= %Y %Y\r\n", idtreg.base, idtreg.limite);
printf("CR0=%Y CR2=%Y CR3=%Y CR4=%Y\r\n", stack->cr0, stack->cr2,
stack->cr3, stack->cr4);
printf("DR0=%Y DR1=%Y DR2=%Y DR3=%Y\r\n", stack->dr0, stack->dr1,
stack->dr2, stack->dr3);
printf("DR6=%Y DR7=%Y\r\n", stack->dr6, stack->dr7);
printf("EFER=%lY\r\n", stack->efer);
printf("STACK\r\n");
if (abs(KERNEL_STACK_ADDR - stack->esp) > 0x10000)
printf("Pile invalide !");
else
{
u32 i = 0;
for (u32 * pointer = stack->esp;
pointer < KERNEL_STACK_ADDR; pointer++)
{
if (i > 0 && i % 10 == 0)
print("\033[10A");
if (i >= 10)
print("\033[25C");
printf("+%d:%Y - %Y\r\n", i++, pointer,
(u32) (*pointer));
}
for (u32 j = 0; j < 10 - (i % 10); j++)
print("\033[01B");
}
}
/*******************************************************************************/