feat: Préparation de la gestion de la mémoire (LDT/GDT)

This commit is contained in:
Nicolas Hordé 2007-04-05 17:33:32 +00:00
parent 8635744ec7
commit 39822e8f9e
5 changed files with 534 additions and 0 deletions

26
include/kmemory.h Normal file
View File

@ -0,0 +1,26 @@
/***********************************/
/* Librairie Kmemory.h */
/* 20 Mars 2007 */
/***********************************/
#ifndef JREKCED_KERNEL_MEMORY
# define JREKCED_KERNEL_MEMORY
# include "type.h"
# define MEMORY_BLOC_SIZE (1024L) /* Taille des blocs */
// Initialise les gestionnaire de memoire.
void Kernel_InitMemory (void *DataMemory, // DataMemory pointe vers la zone de memoire disponible.
UDWORD TotalMemorySize); // TotalMemorySize est la quantite total de memoire disponible.
void * Kernel_mballoc(UDWORD Size); // Alloue SIZE blocs de memoire et retourne un pointeur sur la zone.
// Retourne un pointeur nul si l'allocation est impossible.
int Kernel_mbfree (void *Adresse); // Libere le bloc memoire alloue a l'adresse ADRESSE.
// Retourne -1 si adresse incorrecte et 0 si tout s'est bien deroule.
void * Kernel_mbrealloc (void *Adresse, UDWORD Size); // Redimensionne un bloc, retourne NULL si le bloc
// n'est pas redimensionne.
#endif

85
include/ldt.h Normal file
View File

@ -0,0 +1,85 @@
/***********************************/
/* Librairie LDT.h */
/* 23 Mars 2007 */
/***********************************/
#ifndef JREKCED_LDT
# define JREKCED_LDT
# include "type.h"
# define LDT_BLOC_SIZE (128) /* Nombre de descripteur LDT dans un bloc */
// Types d'acces
# define GLT_ACCESSED (0x1)
# define LDT_DATA (0x0)
# define LDT_DATA_WRITE (0x2)
# define LDT_DATA_EXPAND (0x4)
# define LDT_CODE (0x8)
# define LDT_CODE_READ (0xA)
# define LDT_CODE_CONFORMING (0xD)
// Granularite
# define LDT_BYTE (0x0)
# define LDT_4KB (0x1)
// Mode du CPU
# define LDT_16BIT (0x0)
# define LDT_32BIT (0x1)
typedef struct
{
UWORD Limite_0_15; // Bit 00-15 : Limite (0-15)
UWORD Adresse_0_15; // Bit 16-31 : Adresse (0-15)
UBYTE Adresse_16_23; // Bit 32-39 : Adresse (16-23)
UBYTE Acces : 1; // 0 = System
// 1 = Code ou data
UBYTE Type : 4; // Bit 41-44 : Type
UBYTE DPL : 2; // Spécifie le niveau de privilège du segment
UBYTE Present : 1; // Indique si le segment est en mémoire (bit a 1) ou non (bit a 0)
UBYTE Limite_16_19 : 4; // Bit 48-51 : Limite (16-19)
UBYTE UserDefine : 1; // Bit 52 : Utilisation libre
UBYTE Unused : 1; // Bit 53 : Non utilise (toujours = 0)
UBYTE CPUMode : 1; // Bit 54 : = 0 -> 16-Bit
// = 1 -> 32-Bit
UBYTE Granularite : 1; // Si = 0 : Limite = 1 octet -> 1 Mo
// Si = 1 : Limite = 4 Ko -> 4 Go
UBYTE Adresse_24_31; // Bit 56-63 : Adresse (24-31)
} T_LDT;
typedef struct
{
UWORD Size; // Taille de la GDT
void * Adresse; // Adresse phisique de la GDT;
UWORD Empty;
} T_LDT_reg;
// T_LDT *GDT_BASE = ((T_LDT*)0x0800L); /* Addresse physique ou reside la GDT, le 1e element est toujours null */
T_LDT * LDT_balloc (UWORD Size); // Alloue un bloc de Size LDT
int LDT_bfree (void * Adresse); // Libere un bloc LDT
T_LDT * LDT_brealloc (T_LDT * OldLDT, UWORD NewSize); // Redimensionne un bloc LDT, retourne NULL en cas d'erreur.
T_LDT * LDT_AllocLDT (T_LDT *BaseLDT); // Cherche un LDT libre dans un bloc precedement
// alloue avec LDT_balloc.
// Retourne NULL si aucun bloc disponible.
// Si un bloc libre est trouve, il est marque comme
// utilise et un pointeur sur ce LDT est retourne.
int LDT_FreeLDT (T_LDT *LDT); // Marque le LDT comme non utilise et le met a NULL.
int LDT_MapMemory (T_LDT *LDT, void * Linear, // Met des donnees dans un LDT.
UDWORD Size, // Cette fonction est a tester.
UBYTE Granularite,
UBYTE DPL, UBYTE Type,
UBYTE CPUMode);
#endif

31
include/type.h Normal file
View File

@ -0,0 +1,31 @@
/***********************************/
/* Librairie Type.h */
/* 20 Mars 2007 */
/***********************************/
#ifndef JREKCED_TYPE
# define JREKCED_TYPE
# define NULL (0x0LL)
typedef char int8;
typedef short int16;
typedef int int32;
typedef long long int64;
typedef char BYTE;
typedef short WORD;
typedef long DWORD;
typedef long long QWORD;
typedef signed char SBYTE;
typedef signed short SWORD;
typedef signed long SDWORD;
typedef signed long long SQWORD;
typedef unsigned char UBYTE;
typedef unsigned short UWORD;
typedef unsigned long UDWORD;
typedef unsigned long long UQWORD;
#endif

156
lib/kmemory.c Normal file
View File

@ -0,0 +1,156 @@
/***********************************/
/* Librairie Kmemory.c */
/* 20 Mars 2007 */
/***********************************/
#include <type.h>
#include <Kmemory.h>
/* Structure table d'allocation memoire */
typedef struct
{
UBYTE Used : 1; // = 0 -> La zone memoire est libre.
// = 1 -> La zone memoire est utilisee.
UBYTE Expand : 1; // = 0 -> Fin du bloc.
// = 1 -> Le bloc se prolonge sur le bloc suivant.
UBYTE UnUsed : 6; // Zone libre.
} T_KernelMemoryMap;
T_KernelMemoryMap * BlocAllocate = NULL; // Table d'allocation des blocs memoire.
void * BaseDynAlloc = NULL; // Pointeur sur la zone memoire allouable.
UDWORD MaxMemoryBlocs;
// Initialisation du gestionnaire de memoire.
void Kernel_InitMemory (void *DataMemory, UDWORD TotalMemorySize)
{
UDWORD Boucle;
UDWORD TableBlocs;
UDWORD TotalBlocs;
// Alignement des bloc de memoire a un multiple de MEMORY_BLOC_SIZE
if ( (UDWORD)DataMemory % MEMORY_BLOC_SIZE != 0)
{ DataMemory = ((void*) ((((UDWORD)DataMemory) / MEMORY_BLOC_SIZE) * MEMORY_BLOC_SIZE) + MEMORY_BLOC_SIZE ); };
TotalBlocs = (((void*)TotalMemorySize) - DataMemory) / MEMORY_BLOC_SIZE;
TableBlocs = TotalBlocs / MEMORY_BLOC_SIZE;
MaxMemoryBlocs = TotalBlocs - TableBlocs;
BlocAllocate = (T_KernelMemoryMap *)DataMemory;
BaseDynAlloc = DataMemory + (TableBlocs * MEMORY_BLOC_SIZE);
for (Boucle = 0; Boucle < MaxMemoryBlocs; Boucle++)
{
BlocAllocate [Boucle].Used = 0;
BlocAllocate [Boucle].Expand = 0;
}
}
// Alloue SIZE blocs de memoire
void * Kernel_mballoc(UDWORD Size)
{
UDWORD Counter = 0;
UDWORD Base = 0;
UDWORD Boucle, Boucle2;
if (Size == 0) return NULL;
for (Boucle = 0; Boucle < MaxMemoryBlocs; Boucle++)
{
if (BlocAllocate[Boucle].Used == 0) { Counter++; }
else { Counter = 0; Base = Boucle + 1; }
if (Counter >= Size)
{
if (Base+Size > MaxMemoryBlocs) return NULL;
for (Boucle2=Base; Boucle2 < (Base+Size); Boucle2++)
{
BlocAllocate[Boucle2].Used = 1;
if (Boucle2+1 < (Base+Size) ) { BlocAllocate[Boucle2].Expand = 1; }
else { BlocAllocate[Boucle2].Expand = 0; }
}
return ((void*) (BaseDynAlloc + (Base * MEMORY_BLOC_SIZE) ));
}
}
return NULL;
}
// Libere un bloc memoire
int Kernel_mbfree (void *Adresse)
{
UDWORD Bloc;
if (((Adresse - BaseDynAlloc) % MEMORY_BLOC_SIZE) != 0) return -1;
if ((((UDWORD)Adresse) % MEMORY_BLOC_SIZE) != 0) return -1;
Bloc = (Adresse - BaseDynAlloc) / MEMORY_BLOC_SIZE;
for (; BlocAllocate[Bloc].Expand == 1; Bloc++)
{
BlocAllocate[Bloc].Used = 0;
BlocAllocate[Bloc].Expand = 0;
}
BlocAllocate[Bloc].Used = 0;
BlocAllocate[Bloc].Expand = 0;
return 0;
};
void * Kernel_mbrealloc (void *Adresse, UDWORD Size)
{
UDWORD Bloc, Boucle, OldSize, CopySize;
void * NewAdresse;
if (((Adresse - BaseDynAlloc) % MEMORY_BLOC_SIZE) != 0) return NULL;
Bloc = (Adresse - BaseDynAlloc) / MEMORY_BLOC_SIZE;
if (BlocAllocate[Bloc].Used == 0) return NULL;
for (Boucle = Bloc; BlocAllocate[Boucle].Expand == 1; Boucle++)
{ if (Boucle >= MaxMemoryBlocs) break; };
OldSize = Boucle - Bloc + 1;
// Si pas de changement de taille de bloc, ...
if ( Size == OldSize) return Adresse;
// Si on reduit le nombre de bloc, ...
if ( Size < OldSize)
{
for (Boucle = (Bloc + Size); Boucle < (Bloc + OldSize) ; Boucle++)
{
BlocAllocate[Boucle].Used = 0;
BlocAllocate[Boucle].Expand = 0;
}
BlocAllocate[Size-1].Expand = 0;
return Adresse;
}
// Si on augmente le nombre de bloc
for (Boucle = (Bloc + OldSize); Boucle < (Bloc + Size) ; Boucle++)
{
// Si le bloc ne peut etre simplement agrandit, ...
if ( BlocAllocate[Boucle].Used == 1 )
{
NewAdresse = Kernel_mballoc (Size);
if (NewAdresse == NULL) return NULL;
CopySize = (OldSize * MEMORY_BLOC_SIZE) / sizeof (int64);
for (Boucle = 0; Boucle < CopySize; Boucle++)
{ ((int64*) NewAdresse)[Boucle] = ((int64*) Adresse)[Boucle]; };
Kernel_mbfree (Adresse);
return NewAdresse;
}
}
// Le bloc est simplement agrandit
for (Boucle = (Bloc + OldSize - 1); Boucle < (Bloc + Size) ; Boucle++)
{
BlocAllocate[Boucle].Used = 1;
BlocAllocate[Boucle].Expand = 1;
}
BlocAllocate[Size-1].Expand = 0;
return Adresse;
}
#undef MAX_MEMORY_BLOCS

236
lib/ldt.c Normal file
View File

@ -0,0 +1,236 @@
/***********************************/
/* Librairie LDT.c */
/* 23 Mars 2007 */
/***********************************/
#include "LDT.h"
#include "Kmemory.h"
# define LDT_MANAGER_SIZE (127)
typedef struct // Structure de gestion des bloc LDT
{
void * Next; // Pointeur de chainage
UDWORD Empty;
T_LDT_reg LDTdesc [LDT_MANAGER_SIZE]; // Nombre de blocs LDT
} T_LDT_Manager;
void LDT_initalloc (void *AllocTable, UDWORD Index, UDWORD SetSize, UDWORD TotalSize);
T_LDT_Manager * LDT_mballoc (UWORD Size);
/////////////////////////////////////////////////////////////////////////
T_LDT_Manager * LDT_Manager = NULL;
/////////////////////////////////////////////////////////////////////////
T_LDT * LDT_balloc (UWORD Size) // Alloue un bloc de Size LDT
{
UWORD Boucle;
UDWORD Blocs, Boucle2;
T_LDT_Manager * * ptr_Manager = &LDT_Manager;
T_LDT_Manager * Manager = LDT_Manager;
do
{
if (* ptr_Manager == NULL)
{
* ptr_Manager = Kernel_mballoc (1);
Manager = * ptr_Manager;
Manager->Next = NULL;
for (Boucle = 0; Boucle < LDT_MANAGER_SIZE; Boucle++)
{
Manager->LDTdesc [Boucle].Adresse = NULL;
Manager->LDTdesc [Boucle].Size = NULL;
}
}
for (Boucle = 0; Boucle < LDT_MANAGER_SIZE; Boucle++)
{
if (Manager->LDTdesc [Boucle].Adresse == NULL)
{
Blocs = Size * sizeof(T_LDT);
if (Blocs % MEMORY_BLOC_SIZE == 0)
{ Blocs /= MEMORY_BLOC_SIZE; } else { Blocs = (Blocs / MEMORY_BLOC_SIZE) + 1; }
Manager->LDTdesc [Boucle].Adresse = Kernel_mballoc (Blocs);
if (Manager->LDTdesc [Boucle].Adresse == NULL) return NULL;
Manager->LDTdesc [Boucle].Size = (Blocs * MEMORY_BLOC_SIZE) / sizeof(T_LDT);
// Mise a zero de la LDT
for (Boucle2 = 0; Boucle2 < Manager->LDTdesc [Boucle].Size; Boucle2++)
{ ((int64*) Manager->LDTdesc [Boucle].Adresse)[Boucle2] = NULL; }
return Manager->LDTdesc [Boucle].Adresse;
}
}
*ptr_Manager = Manager;
Manager = Manager->Next;
} while (1);
}
int LDT_bfree (void * Adresse) // Libere un bloc LDT
{
UWORD Boucle, Boucle2;
int RetVal;
T_LDT_Manager * * ptr_Manager = &LDT_Manager;
T_LDT_Manager * Manager = LDT_Manager;
do
{
if (*ptr_Manager == NULL) { return -1; }
for (Boucle = 0; Boucle < LDT_MANAGER_SIZE; Boucle++)
{
if (Manager->LDTdesc [Boucle].Adresse == Adresse)
{
RetVal = Kernel_mbfree(Manager->LDTdesc [Boucle].Adresse);
if (Boucle == 0)
{
Kernel_mbfree (*ptr_Manager);
*ptr_Manager = NULL;
return RetVal;
}
else
{
for (Boucle2 = Boucle; Boucle2 < LDT_MANAGER_SIZE-1; Boucle2++)
{ Manager->LDTdesc [Boucle2] = Manager->LDTdesc [Boucle2+1]; }
Manager->LDTdesc [Boucle2+1].Size = NULL;
Manager->LDTdesc [Boucle2+1].Adresse = NULL;
}
Manager->LDTdesc [LDT_MANAGER_SIZE-1].Size = NULL;
Manager->LDTdesc [LDT_MANAGER_SIZE-1].Adresse = NULL;
return RetVal;
}
}
*ptr_Manager = Manager;
Manager = Manager->Next;
} while (1);
}
T_LDT * LDT_brealloc (T_LDT * OldLDT, UWORD NewSize)
{
T_LDT * NewLDT;
UDWORD Blocs;
UWORD Boucle;
T_LDT_Manager * * ptr_Manager = &LDT_Manager;
T_LDT_Manager * Manager = LDT_Manager;
Blocs = NewSize * sizeof(T_LDT);
if (Blocs % MEMORY_BLOC_SIZE == 0)
{ Blocs /= MEMORY_BLOC_SIZE; } else { Blocs = (Blocs / MEMORY_BLOC_SIZE) + 1; }
do
{
if (*ptr_Manager == NULL) { return NULL; }
for (Boucle = 0; Boucle < LDT_MANAGER_SIZE; Boucle++)
{
if (Manager->LDTdesc [Boucle].Adresse == OldLDT)
{
NewLDT = Kernel_mbrealloc (OldLDT, Blocs);
if (NewLDT == NULL) return NULL;
Manager->LDTdesc [Boucle].Adresse = NewLDT;
Manager->LDTdesc [Boucle].Size = NewSize;
return NewLDT;
}
}
*ptr_Manager = Manager;
Manager = Manager->Next;
} while (1);
}
///////////////////////////////////////////////////////////////////////
T_LDT * LDT_AllocLDT (T_LDT *BaseLDT)
{
UWORD Boucle;
UDWORD Boucle2;
UDWORD Size;
T_LDT_Manager * Manager = LDT_Manager;
if (BaseLDT == NULL) return NULL;
do
{
if (Manager == NULL) { return NULL; }
for (Boucle = 0; Boucle < LDT_MANAGER_SIZE; Boucle++)
{
Size = Manager->LDTdesc [Boucle].Size;
if (Manager->LDTdesc [Boucle].Adresse == ((void*)BaseLDT) )
{
for (Boucle2 = 1; Boucle2 < Size; Boucle2++) // Le 1e LDT reste null
{
if ( BaseLDT[Boucle2].UserDefine == 0 )
{
BaseLDT[Boucle2].UserDefine = 1;
return BaseLDT+Boucle2;
};
}
return NULL;
}
}
Manager = Manager->Next;
} while (1);
}
int LDT_FreeLDT (T_LDT *LDT) // Marque le LDT comme non utilise et le met a NULL
{
if ( ((UDWORD)LDT & 0x07L) != NULL) { return -2; }
if (LDT->UserDefine == 0) { return -1; }
*((int64*)LDT) = NULL;
return 0;
}
///////////////////////////////////////////////////////////////////////
int LDT_MapMemory (T_LDT *LDT, void * Linear, UDWORD Size, UBYTE Granularite, UBYTE DPL, UBYTE Type, UBYTE CPUMode)
{
if ( ((UDWORD)LDT & 0x07L) != NULL) { return -2; }
LDT->Adresse_0_15 = (DWORD)Linear & 0x0000FFFFL;
LDT->Adresse_16_23 = ((DWORD)Linear >> 16) & 0x000000FFL;
LDT->Adresse_24_31 = ((DWORD)Linear >> 24) & 0x000000FFL;
LDT->Limite_0_15 = Size & 0x0000FFFFL;
LDT->Limite_16_19 = (Size >> 16) & 0x0000000FL;
LDT->Granularite = Granularite;
LDT->Type = Type;
LDT->DPL = DPL;
LDT->CPUMode = CPUMode;
LDT->Present = 1;
LDT->UserDefine = 1;
return 0;
}
int LDT_load (T_LDT *LDT)
{
UWORD Boucle;
T_LDT_Manager * * ptr_Manager = &LDT_Manager;
T_LDT_Manager * Manager = LDT_Manager;
do
{
if (*ptr_Manager == NULL) { return -1; }
for (Boucle = 0; Boucle < LDT_MANAGER_SIZE; Boucle++)
{
if (Manager->LDTdesc [Boucle].Adresse == LDT)
{
asm("lgdt %0\n" : : "m" (Manager->LDTdesc [Boucle]));
return 0;
}
}
*ptr_Manager = Manager;
Manager = Manager->Next;
} while (1);
}