mirror of
https://gitlab.rtems.org/rtems/rtos/rtems.git
synced 2025-12-27 06:58:19 +00:00
bsp/pc386: Move libcpu content to bsps
This patch is a part of the BSP source reorganization. Update #3285.
This commit is contained in:
@@ -171,6 +171,10 @@ libbsp_a_SOURCES += wd8003/wd8003.c
|
||||
endif
|
||||
|
||||
libbsp_a_SOURCES += ../../../../../../bsps/i386/shared/cache/cache.c
|
||||
libbsp_a_SOURCES += ../../../../../../bsps/i386/pc386/start/cpuModel.S
|
||||
libbsp_a_SOURCES += ../../../../../../bsps/i386/pc386/start/displayCpu.c
|
||||
libbsp_a_SOURCES += ../../../../../../bsps/i386/pc386/start/idtr.S
|
||||
libbsp_a_SOURCES += ../../../../../../bsps/i386/pc386/start/page.c
|
||||
|
||||
libbsp_a_LIBADD = ../../../libcpu/@RTEMS_CPU@/page.rel
|
||||
libbsp_a_LIBADD += ../../../libcpu/@RTEMS_CPU@/score.rel
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
ACLOCAL_AMFLAGS = -I ../../../aclocal
|
||||
|
||||
noinst_PROGRAMS =
|
||||
|
||||
include $(top_srcdir)/../../../automake/compile.am
|
||||
|
||||
noinst_PROGRAMS += score.rel
|
||||
score_rel_SOURCES = displayCpu.c cpuModel.S cpuModel.h idtr.S cpu.h
|
||||
score_rel_CPPFLAGS = $(AM_CPPFLAGS)
|
||||
score_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
|
||||
|
||||
noinst_PROGRAMS += page.rel
|
||||
page_rel_SOURCES = page.c page.h
|
||||
page_rel_CPPFLAGS = $(AM_CPPFLAGS)
|
||||
page_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
|
||||
|
||||
include $(top_srcdir)/../../../automake/local.am
|
||||
@@ -1,28 +0,0 @@
|
||||
## Process this file with autoconf to produce a configure script.
|
||||
|
||||
AC_PREREQ([2.69])
|
||||
AC_INIT([rtems-c-src-lib-libcpu-i386],[_RTEMS_VERSION],[https://devel.rtems.org/newticket])
|
||||
AC_CONFIG_SRCDIR([idtr.S])
|
||||
RTEMS_TOP([../../../../..],[../../..])
|
||||
RTEMS_SOURCE_TOP
|
||||
RTEMS_BUILD_TOP
|
||||
|
||||
RTEMS_CANONICAL_TARGET_CPU
|
||||
|
||||
AM_INIT_AUTOMAKE([no-define foreign subdir-objects 1.12.2])
|
||||
AM_MAINTAINER_MODE
|
||||
|
||||
RTEMS_ENV_RTEMSBSP
|
||||
|
||||
RTEMS_PROJECT_ROOT
|
||||
|
||||
RTEMS_PROG_CC_FOR_TARGET
|
||||
AM_PROG_CC_C_O
|
||||
RTEMS_CANONICALIZE_TOOLS
|
||||
RTEMS_PROG_CCAS
|
||||
|
||||
RTEMS_AMPOLISH3
|
||||
|
||||
# Explicitly list all Makefiles here
|
||||
AC_CONFIG_FILES([Makefile])
|
||||
AC_OUTPUT
|
||||
@@ -1,273 +0,0 @@
|
||||
/* cpuModel.S
|
||||
*
|
||||
* This file contains all assembly code for the Intel Cpu identification.
|
||||
* It is based on linux cpu detection code.
|
||||
*
|
||||
* Intel also provides public similar code in the book
|
||||
* called :
|
||||
*
|
||||
* Pentium Processor Family
|
||||
* Developer Family
|
||||
* Volume 3 : Architecture and Programming Manual
|
||||
*
|
||||
* At the following place :
|
||||
*
|
||||
* Chapter 5 : Feature determination
|
||||
* Chapter 25: CPUID instruction
|
||||
*
|
||||
* COPYRIGHT (c) 1998 valette@crf.canon.fr
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.org/license/LICENSE.
|
||||
*/
|
||||
|
||||
#include <rtems/asm.h>
|
||||
#include <rtems/score/registers.h>
|
||||
|
||||
BEGIN_CODE
|
||||
PUBLIC(checkCPUtypeSetCr0);
|
||||
/*
|
||||
* check Processor type: 386, 486, 6x86(L) or CPUID capable processor
|
||||
*/
|
||||
|
||||
SYM (checkCPUtypeSetCr0):
|
||||
/*
|
||||
* Assume 386 for now
|
||||
*/
|
||||
movl $3, SYM (x86)
|
||||
/*
|
||||
* Start using the EFLAGS AC bit determination method described in
|
||||
* the book mentioned above page 5.1. If this bit can be set we
|
||||
* have a 486 or above.
|
||||
*/
|
||||
pushfl /* save EFLAGS */
|
||||
|
||||
pushfl /* Get EFLAGS in EAX */
|
||||
popl eax
|
||||
|
||||
movl eax,ecx /* save original EFLAGS in ECX */
|
||||
xorl $EFLAGS_ALIGN_CHECK,eax /* flip AC bit in EAX */
|
||||
pushl eax /* set EAX as EFLAGS */
|
||||
popfl
|
||||
pushfl /* Get new EFLAGS in EAX */
|
||||
popl eax
|
||||
|
||||
xorl ecx,eax /* check if AC bit changed */
|
||||
andl $EFLAGS_ALIGN_CHECK,eax
|
||||
je is386 /* If not : we have a 386 */
|
||||
/*
|
||||
* Assume 486 for now
|
||||
*/
|
||||
movl $4,SYM (x86)
|
||||
movl ecx,eax /* Restore orig EFLAGS in EAX */
|
||||
xorl $EFLAGS_ID,eax /* flip ID flag */
|
||||
pushl eax /* set EAX as EFLAGS */
|
||||
popfl
|
||||
pushfl /* Get new EFLAGS in EAX */
|
||||
popl eax
|
||||
|
||||
xorl ecx,eax /* check if ID bit changed */
|
||||
andl $EFLAGS_ID,eax
|
||||
|
||||
/*
|
||||
* if we are on a straight 486DX,
|
||||
* SX, or 487SX we can't change it
|
||||
* OTOH 6x86MXs and MIIs check OK
|
||||
* Also if we are on a Cyrix 6x86(L)
|
||||
*/
|
||||
je is486x
|
||||
|
||||
isnew:
|
||||
/*
|
||||
* restore original EFLAGS
|
||||
*/
|
||||
popfl
|
||||
incl SYM(have_cpuid) /* we have CPUID instruction */
|
||||
|
||||
/*
|
||||
* Addressable Processor Ids
|
||||
*
|
||||
* CPUID.(EAX=4, ECX=0):EAX[31:26] + 1 = Y)
|
||||
*/
|
||||
movl $4, eax
|
||||
movl $0, ecx
|
||||
cpuid
|
||||
movl eax,SYM(x86_capability_cores)
|
||||
|
||||
/* use it to get :
|
||||
* processor type,
|
||||
* processor model,
|
||||
* processor mask,
|
||||
* by using it with EAX = 1
|
||||
*/
|
||||
movl $1, eax
|
||||
cpuid
|
||||
movl ebx,SYM(x86_capability_ebx) /* store ebx feature info */
|
||||
movl ecx,SYM(x86_capability_x) /* store ecx feature flags */
|
||||
|
||||
movb al, cl /* save reg for future use */
|
||||
|
||||
andb $0x0f,ah /* mask processor family */
|
||||
movb ah,SYM (x86) /* put result in x86 var */
|
||||
|
||||
andb $0xf0, al /* get model */
|
||||
shrb $4, al
|
||||
movb al,SYM (x86_model) /* store it in x86_model */
|
||||
|
||||
andb $0x0f, cl /* get mask revision */
|
||||
movb cl,SYM (x86_mask) /* store it in x86_mask */
|
||||
|
||||
movl edx,SYM(x86_capability) /* store feature flags in x86_capability */
|
||||
|
||||
/* get vendor info by using CPUID with EXA = 0 */
|
||||
xorl eax, eax
|
||||
cpuid
|
||||
|
||||
/*
|
||||
* store results contained in ebx, edx, ecx in
|
||||
* x86_vendor_id variable.
|
||||
*/
|
||||
movl ebx,SYM(x86_vendor_id)
|
||||
movl edx,SYM(x86_vendor_id)+4
|
||||
movl ecx,SYM(x86_vendor_id)+8
|
||||
|
||||
movl cr0,eax /* 486+ */
|
||||
andl $(CR0_PAGING | CR0_PROTECTION_ENABLE | CR0_EXTENSION_TYPE), eax
|
||||
orl $(CR0_ALIGMENT_MASK | CR0_WRITE_PROTECT | CR0_NUMERIC_ERROR | CR0_MONITOR_COPROC),eax
|
||||
jmp 2f
|
||||
|
||||
/* Now we test if we have a Cyrix 6x86(L). We didn't test before to avoid
|
||||
* clobbering the new BX chipset used with the Pentium II, which has a register
|
||||
* at the same addresses as those used to access the Cyrix special configuration
|
||||
* registers (CCRs).
|
||||
*/
|
||||
/*
|
||||
* A Cyrix/IBM 6x86(L) preserves flags after dividing 5 by 2
|
||||
* (and it _must_ be 5 divided by 2) while other CPUs change
|
||||
* them in undefined ways. We need to know this since we may
|
||||
* need to enable the CPUID instruction at least.
|
||||
* We couldn't use this test before since the PPro and PII behave
|
||||
* like Cyrix chips in this respect.
|
||||
*/
|
||||
is486x: xor ax,ax
|
||||
sahf
|
||||
movb $5,al
|
||||
movb $2,bl
|
||||
div bl
|
||||
lahf
|
||||
cmpb $2,ah
|
||||
jne ncyrix
|
||||
/*
|
||||
* N.B. The pattern of accesses to 0x22 and 0x23 is *essential*
|
||||
* so do not try to "optimize" it! For the same reason we
|
||||
* do all this with interrupts off.
|
||||
*/
|
||||
#define setCx86(reg, val) \
|
||||
movb reg,al; \
|
||||
outb al,$0x22; \
|
||||
movb val,al; \
|
||||
outb al,$0x23
|
||||
|
||||
#define getCx86(reg) \
|
||||
movb reg,al; \
|
||||
outb al,$0x22; \
|
||||
inb $0x23,al
|
||||
|
||||
cli
|
||||
getCx86($0xc3) /* get CCR3 */
|
||||
movb al,cl /* Save old value */
|
||||
movb al,bl
|
||||
andb $0x0f,bl /* Enable access to all config registers */
|
||||
orb $0x10,bl /* by setting bit 4 */
|
||||
setCx86($0xc3,bl)
|
||||
|
||||
getCx86($0xe8) /* now we can get CCR4 */
|
||||
orb $0x80,al /* and set bit 7 (CPUIDEN) */
|
||||
movb al,bl /* to enable CPUID execution */
|
||||
setCx86($0xe8,bl)
|
||||
|
||||
getCx86($0xfe) /* DIR0 : let's check this is a 6x86(L) */
|
||||
andb $0xf0,al /* should be 3xh */
|
||||
cmpb $0x30,al
|
||||
jne n6x86
|
||||
getCx86($0xe9) /* CCR5 : we reset the SLOP bit */
|
||||
andb $0xfd,al /* so that udelay calculation */
|
||||
movb al,bl /* is correct on 6x86(L) CPUs */
|
||||
setCx86($0xe9,bl)
|
||||
setCx86($0xc3,cl) /* Restore old CCR3 */
|
||||
sti
|
||||
jmp isnew /* We enabled CPUID now */
|
||||
|
||||
n6x86: setCx86($0xc3,cl) /* Restore old CCR3 */
|
||||
sti
|
||||
ncyrix: /* restore original EFLAGS */
|
||||
popfl
|
||||
movl cr0,eax /* 486 */
|
||||
andl $(CR0_PAGING | CR0_EXTENSION_TYPE | CR0_PROTECTION_ENABLE),eax /* Save PG,PE,ET */
|
||||
orl $(CR0_ALIGMENT_MASK | CR0_WRITE_PROTECT | CR0_NUMERIC_ERROR | CR0_MONITOR_COPROC),eax /* set AM, WP, NE and MP */
|
||||
jmp 2f
|
||||
is386: /* restore original EFLAGS */
|
||||
popfl
|
||||
movl cr0,eax /* 386 */
|
||||
andl $(CR0_PAGING | CR0_EXTENSION_TYPE | CR0_PROTECTION_ENABLE),eax /* Save PG,PE,ET */
|
||||
orl $CR0_MONITOR_COPROC,eax /* set MP */
|
||||
2: movl eax,cr0
|
||||
call check_x87
|
||||
ret
|
||||
|
||||
|
||||
/*
|
||||
* We depend on ET to be correct. This checks for 287/387.
|
||||
*/
|
||||
check_x87:
|
||||
movb $0,SYM(hard_math)
|
||||
clts
|
||||
fninit
|
||||
fstsw ax
|
||||
cmpb $0,al
|
||||
je 1f
|
||||
movl cr0,eax /* no coprocessor: have to set bits */
|
||||
xorl $4,eax /* set EM */
|
||||
movl eax,cr0
|
||||
ret
|
||||
.align 16
|
||||
1: movb $1,SYM(hard_math)
|
||||
.byte 0xDB,0xE4 /* fsetpm for 287, ignored by 387 */
|
||||
ret
|
||||
|
||||
END_CODE
|
||||
|
||||
BEGIN_DATA
|
||||
PUBLIC(x86)
|
||||
PUBLIC(have_cpuid)
|
||||
PUBLIC(x86_model)
|
||||
PUBLIC(x86_mask)
|
||||
PUBLIC(x86_capability)
|
||||
PUBLIC(x86_capability_ebx)
|
||||
PUBLIC(x86_capability_x)
|
||||
PUBLIC(x86_capability_cores)
|
||||
PUBLIC(x86_vendor_id)
|
||||
PUBLIC(hard_math)
|
||||
|
||||
SYM(x86):
|
||||
.byte 0
|
||||
SYM(have_cpuid):
|
||||
.long 0
|
||||
SYM(x86_model):
|
||||
.byte 0
|
||||
SYM(x86_mask):
|
||||
.byte 0
|
||||
SYM(x86_capability):
|
||||
.long 0
|
||||
SYM(x86_capability_ebx):
|
||||
.long 0
|
||||
SYM(x86_capability_x):
|
||||
.long 0
|
||||
SYM(x86_capability_cores):
|
||||
.long 0
|
||||
SYM(x86_vendor_id):
|
||||
.zero 13
|
||||
SYM(hard_math):
|
||||
.byte 0
|
||||
END_DATA
|
||||
@@ -1,243 +0,0 @@
|
||||
/*
|
||||
* This file contains code for displaying the Intel Cpu identification
|
||||
* that has been performed by checkCPUtypeSetCr0 function.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file was updated by Joel Sherrill <joel.sherrill@oarcorp.com>
|
||||
* to define more capability bits, pick up more CPU model information,
|
||||
* and add more model strings. --joel (April 2010)
|
||||
*
|
||||
* COPYRIGHT (c) 1998 valette@crf.canon.fr
|
||||
* COPYRIGHT (c) 2010 OAR Corporation
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.org/license/LICENSE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Tell us the machine setup..
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <rtems/score/cpu.h>
|
||||
#include <string.h>
|
||||
#include <libcpu/cpuModel.h>
|
||||
#include <rtems/bspIo.h>
|
||||
#include <rtems.h>
|
||||
|
||||
unsigned char Cx86_step = 0;
|
||||
|
||||
static const char *Cx86_type[] = {
|
||||
"unknown", "1.3", "1.4", "1.5", "1.6",
|
||||
"2.4", "2.5", "2.6", "2.7 or 3.7", "4.2"
|
||||
};
|
||||
|
||||
static const char *i486model(unsigned int nr)
|
||||
{
|
||||
static const char *model[] = {
|
||||
"0","DX","SX","DX/2","4","SX/2","6","DX/2-WB","DX/4","DX/4-WB",
|
||||
"10","11","12","13","Am5x86-WT","Am5x86-WB"
|
||||
};
|
||||
|
||||
if (nr < sizeof(model)/sizeof(char *))
|
||||
return model[nr];
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const char * i586model(unsigned int nr)
|
||||
{
|
||||
static const char *model[] = {
|
||||
"0", "Pentium 60/66","Pentium 75+","OverDrive PODP5V83",
|
||||
"Pentium MMX", NULL, NULL, "Mobile Pentium 75+",
|
||||
"Mobile Pentium MMX"
|
||||
};
|
||||
if (nr < sizeof(model)/sizeof(char *))
|
||||
return model[nr];
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const char *Cx86model(void)
|
||||
{
|
||||
unsigned char nr6x86 = 0;
|
||||
static const char *model[] = {
|
||||
"unknown", "6x86", "6x86L", "6x86MX", "MII"
|
||||
};
|
||||
|
||||
switch (x86) {
|
||||
case 5:
|
||||
/* cx8 flag only on 6x86L */
|
||||
nr6x86 = ((x86_capability & (1 << 8)) ? 2 : 1);
|
||||
break;
|
||||
case 6:
|
||||
nr6x86 = 3;
|
||||
break;
|
||||
default:
|
||||
nr6x86 = 0;
|
||||
}
|
||||
|
||||
/* We must get the stepping number by reading DIR1 */
|
||||
outport_byte(0x22,0xff);
|
||||
inport_byte(0x23, x86_mask);
|
||||
switch (x86_mask) {
|
||||
case 0x03:
|
||||
Cx86_step = 1; /* 6x86MX Rev 1.3 */
|
||||
break;
|
||||
case 0x04:
|
||||
Cx86_step = 2; /* 6x86MX Rev 1.4 */
|
||||
break;
|
||||
case 0x05:
|
||||
Cx86_step = 3; /* 6x86MX Rev 1.5 */
|
||||
break;
|
||||
case 0x06:
|
||||
Cx86_step = 4; /* 6x86MX Rev 1.6 */
|
||||
break;
|
||||
case 0x14:
|
||||
Cx86_step = 5; /* 6x86 Rev 2.4 */
|
||||
break;
|
||||
case 0x15:
|
||||
Cx86_step = 6; /* 6x86 Rev 2.5 */
|
||||
break;
|
||||
case 0x16:
|
||||
Cx86_step = 7; /* 6x86 Rev 2.6 */
|
||||
break;
|
||||
case 0x17:
|
||||
Cx86_step = 8; /* 6x86 Rev 2.7 or 3.7 */
|
||||
break;
|
||||
case 0x22:
|
||||
Cx86_step = 9; /* 6x86L Rev 4.2 */
|
||||
break;
|
||||
default:
|
||||
Cx86_step = 0;
|
||||
}
|
||||
return model[nr6x86];
|
||||
}
|
||||
|
||||
static const char * i686model(unsigned int nr)
|
||||
{
|
||||
static const char *model[] = {
|
||||
"PPro A-step",
|
||||
"Pentium Pro"
|
||||
};
|
||||
if (nr < sizeof(model)/sizeof(char *))
|
||||
return model[nr];
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct cpu_model_info {
|
||||
int x86;
|
||||
char *model_names[16];
|
||||
};
|
||||
|
||||
static struct cpu_model_info amd_models[] = {
|
||||
{ 4,
|
||||
{ NULL, NULL, NULL, "DX/2", NULL, NULL, NULL, "DX/2-WB", "DX/4",
|
||||
"DX/4-WB", NULL, NULL, NULL, NULL, "Am5x86-WT", "Am5x86-WB" }},
|
||||
{ 5,
|
||||
{ "K5/SSA5 (PR-75, PR-90, PR-100)", "K5 (PR-120, PR-133)",
|
||||
"K5 (PR-166)", "K5 (PR-200)", NULL, NULL,
|
||||
"K6 (166 - 266)", "K6 (166 - 300)", "K6-2 (200 - 450)",
|
||||
"K6-3D-Plus (200 - 450)", NULL, NULL, NULL, NULL, NULL, NULL }},
|
||||
};
|
||||
|
||||
static const char * AMDmodel(void)
|
||||
{
|
||||
const char *p=NULL;
|
||||
int i;
|
||||
|
||||
if (x86_model < 16)
|
||||
for (i=0; i<sizeof(amd_models)/sizeof(struct cpu_model_info); i++)
|
||||
if (amd_models[i].x86 == x86) {
|
||||
p = amd_models[i].model_names[(int)x86_model];
|
||||
break;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
static const char * getmodel(int x86, int model)
|
||||
{
|
||||
const char *p = NULL;
|
||||
static char nbuf[12];
|
||||
|
||||
if (strncmp(x86_vendor_id, "Cyrix", 5) == 0)
|
||||
p = Cx86model();
|
||||
else if(strcmp(x86_vendor_id, "AuthenticAMD")==0)
|
||||
p = AMDmodel();
|
||||
else {
|
||||
switch (x86) {
|
||||
case 4:
|
||||
p = i486model(model);
|
||||
break;
|
||||
case 5:
|
||||
p = i586model(model);
|
||||
break;
|
||||
case 6:
|
||||
p = i686model(model);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (p)
|
||||
return p;
|
||||
|
||||
sprintf(nbuf, "%d", model);
|
||||
return nbuf;
|
||||
}
|
||||
|
||||
void printCpuInfo(void)
|
||||
{
|
||||
int i,j;
|
||||
static const char *x86_cap_flags[] = {
|
||||
"fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce",
|
||||
"cx8", "apic", "10", "sep", "mtrr", "pge", "mca", "cmov",
|
||||
"pat", "pse36", "psn", "cflsh", "20", "ds", "acpi", "mmx",
|
||||
"fxsr", "sse", "sse2", "ss", "htt", "tm", "30", "pbe"
|
||||
};
|
||||
static const char *x86_cap_x_flags[] = {
|
||||
"sse3", "pclmulqdq", "dtes64", "monitor", "ds-cpl", "vmx", "smx", "est",
|
||||
"tm2", "ssse3", "cnxt-id", "11", "12", "cmpxchg16b", "xtpr", "pdcm",
|
||||
"16", "pcid", "dca", "sse4.1", "sse4.2", "x2APIC", "movbe", "popcnt"
|
||||
"24", "aesni", "xsave", "xsave", "avx", "29", "30", "31"
|
||||
};
|
||||
|
||||
printk("cpu : %c86\n", x86+'0');
|
||||
printk("model : %s\n",
|
||||
have_cpuid ? getmodel(x86, x86_model) : "unknown");
|
||||
if (x86_vendor_id [0] == '\0')
|
||||
strcpy(x86_vendor_id, "unknown");
|
||||
printk("vendor_id : %s\n", x86_vendor_id);
|
||||
|
||||
if (x86_mask) {
|
||||
if (strncmp(x86_vendor_id, "Cyrix", 5) != 0) {
|
||||
printk("stepping : %d\n", x86_mask);
|
||||
}
|
||||
else { /* we have a Cyrix */
|
||||
printk("stepping : %s\n", Cx86_type[Cx86_step]);
|
||||
}
|
||||
} else
|
||||
printk("stepping : unknown\n");
|
||||
|
||||
printk("fpu : %s\n", (hard_math ? "yes" : "no"));
|
||||
printk("cpuid : %s\n", (have_cpuid ? "yes" : "no"));
|
||||
printk("flags :");
|
||||
for ( i = j = 0 ; i < 32 ; i++ ) {
|
||||
if ( x86_capability & (1 << i) ) {
|
||||
if ( j && 0 == (j & 7) )
|
||||
printk("\n ");
|
||||
printk(" %s", x86_cap_flags[i]);
|
||||
j++;
|
||||
}
|
||||
}
|
||||
printk("\n");
|
||||
printk("flags (ext.):");
|
||||
for ( i = j = 0 ; i < 32 ; i++ ) {
|
||||
if ( x86_capability_x & (1 << i) ) {
|
||||
if ( j && 0 == (j & 7) )
|
||||
printk("\n ");
|
||||
printk(" %s", x86_cap_x_flags[i]);
|
||||
j++;
|
||||
}
|
||||
}
|
||||
printk("\n");
|
||||
printk( "x86_capability_ebx=0x%08x\n", x86_capability_ebx);
|
||||
printk( "x86_capability_cores=0x%08x\n", x86_capability_cores);
|
||||
}
|
||||
@@ -1,115 +0,0 @@
|
||||
/* cpu_asm.S
|
||||
*
|
||||
* This file contains all assembly code for the Intel i386 IDT
|
||||
* manipulation.
|
||||
*
|
||||
* COPYRIGHT (c) 1998 valette@crf.canon.fr
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.org/license/LICENSE.
|
||||
*/
|
||||
|
||||
#include <rtems/asm.h>
|
||||
|
||||
BEGIN_CODE
|
||||
/*
|
||||
* C callable function enabling to get easilly usable info from
|
||||
* the actual value of IDT register.
|
||||
*
|
||||
extern void i386_get_info_from_IDTR (interrupt_gate_descriptor** table,
|
||||
unsigned* limit);
|
||||
*/
|
||||
PUBLIC (i386_get_info_from_IDTR)
|
||||
PUBLIC (i386_set_IDTR)
|
||||
PUBLIC (i386_get_info_from_GDTR)
|
||||
PUBLIC (i386_set_GDTR)
|
||||
|
||||
SYM (i386_get_info_from_IDTR):
|
||||
movl 4(esp), ecx /* get location where table address */
|
||||
/* must be stored */
|
||||
movl 8(esp), edx /* get location table size must be stored */
|
||||
|
||||
subl $6, esp /* let room to prepare 48 bit IDTR */
|
||||
|
||||
sidt (esp) /* get 48 bit IDTR value */
|
||||
|
||||
movl 2(esp), eax /* get base */
|
||||
movl eax, (ecx)
|
||||
|
||||
movzwl (esp), eax /* get limit */
|
||||
movl eax, (edx)
|
||||
|
||||
addl $6, esp /* restore %esp */
|
||||
ret
|
||||
|
||||
/*
|
||||
* C callable function enabling to change the value of IDT register. Must be called
|
||||
* with inmterrupt masked at processor level!!!.
|
||||
*
|
||||
extern void i386_set_IDTR (interrupt_gate_descriptor* table,
|
||||
unsigned limit);
|
||||
*/
|
||||
SYM (i386_set_IDTR):
|
||||
|
||||
leal 4(esp), edx /* load in edx address of input */
|
||||
/* parameter "table" */
|
||||
|
||||
movl (edx), eax /* load base into eax */
|
||||
movl 4(edx), ecx /* load limit into ecx */
|
||||
|
||||
movw cx, (edx) /* prepare 48 bit pointer */
|
||||
movl eax, 2(edx)
|
||||
|
||||
lidt (edx)
|
||||
|
||||
ret
|
||||
/*
|
||||
*
|
||||
* C callable function enabling to get easilly usable info from
|
||||
* the actual value of GDT register.
|
||||
extern void i386_get_info_from_GDTR (segment_descriptors** table,
|
||||
uint16_t* limit);
|
||||
*/
|
||||
|
||||
SYM (i386_get_info_from_GDTR):
|
||||
movl 4(esp), ecx /* get location where table address */
|
||||
/* must be stored */
|
||||
movl 8(esp), edx /* get location table size must be stored */
|
||||
|
||||
subl $6, esp /* let room to prepare 48 bit GDTR */
|
||||
|
||||
sgdt (esp) /* get 48 bit GDTR value */
|
||||
|
||||
movl 2(esp), eax /* get base */
|
||||
movl eax, (ecx)
|
||||
|
||||
movzwl (esp), eax /* get limit */
|
||||
movw ax, (edx)
|
||||
|
||||
addl $6, esp /* restore %esp */
|
||||
ret
|
||||
|
||||
/*
|
||||
* C callable function enabling to change the value of GDT register.
|
||||
* Must be called with interrupts masked at processor level!!!.
|
||||
* extern void i386_set_GDTR (segment_descriptors*, uint16_t limit);
|
||||
*/
|
||||
SYM (i386_set_GDTR):
|
||||
|
||||
leal 4(esp), edx /* load in edx address of input */
|
||||
/* parameter "table" */
|
||||
|
||||
movl (edx), eax /* load base into eax */
|
||||
movl 4(edx), ecx /* load limit into ecx */
|
||||
|
||||
movw cx, (edx) /* prepare 48 bit pointer */
|
||||
movl eax, 2(edx)
|
||||
|
||||
lgdt (edx)
|
||||
|
||||
ret
|
||||
|
||||
END_CODE
|
||||
|
||||
END
|
||||
@@ -1,519 +0,0 @@
|
||||
/*
|
||||
* page.c :- This file contains implementation of C function to
|
||||
* Instanciate paging. More detailled information
|
||||
* can be found on Intel site and more precisely in
|
||||
* the following book :
|
||||
*
|
||||
* Pentium Processor familly
|
||||
* Developper's Manual
|
||||
*
|
||||
* Volume 3 : Architecture and Programming Manual
|
||||
*
|
||||
* Copyright (C) 1999 Emmanuel Raguet (raguet@crf.canon.fr)
|
||||
* Canon Centre Recherche France.
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.org/license/LICENSE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <rtems.h>
|
||||
#include <rtems/score/cpu.h>
|
||||
#include <libcpu/page.h>
|
||||
|
||||
#define MEMORY_SIZE 0x4000000 /* 64Mo */
|
||||
|
||||
static int directoryEntry=0;
|
||||
static int tableEntry=0;
|
||||
static page_directory *pageDirectory;
|
||||
|
||||
extern uint32_t bsp_mem_size;
|
||||
|
||||
/*************************************************************************/
|
||||
/************** IT IS A ONE-TO-ONE TRANSLATION ***************************/
|
||||
/*************************************************************************/
|
||||
|
||||
|
||||
/*
|
||||
* Disable the paging
|
||||
*/
|
||||
void _CPU_disable_paging(void)
|
||||
{
|
||||
unsigned int regCr0;
|
||||
|
||||
rtems_cache_flush_entire_data();
|
||||
regCr0 = i386_get_cr0();
|
||||
regCr0 &= ~(CR0_PAGING);
|
||||
i386_set_cr0( regCr0 );
|
||||
}
|
||||
|
||||
/*
|
||||
* Enable the paging
|
||||
*/
|
||||
void _CPU_enable_paging(void)
|
||||
{
|
||||
unsigned int regCr0;
|
||||
|
||||
regCr0 = i386_get_cr0();
|
||||
regCr0 |= CR0_PAGING;
|
||||
i386_set_cr0( regCr0 );
|
||||
rtems_cache_flush_entire_data();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Initialize the paging with 1-to-1 mapping
|
||||
*/
|
||||
|
||||
int init_paging(void)
|
||||
{
|
||||
int nbPages;
|
||||
int nbInitPages;
|
||||
char *Tables;
|
||||
unsigned int regCr3;
|
||||
page_table *pageTable;
|
||||
unsigned int physPage;
|
||||
int nbTables=0;
|
||||
|
||||
nbPages = ( (bsp_mem_size - 1) / PG_SIZE ) + 1;
|
||||
nbTables = ( (bsp_mem_size - 1) / FOUR_MB ) + 2;
|
||||
|
||||
/* allocate 1 page more to page alignement */
|
||||
Tables = (char *)malloc( (nbTables + 1)*sizeof(page_table) );
|
||||
if ( Tables == NULL ){
|
||||
return -1; /*unable to allocate memory */
|
||||
}
|
||||
|
||||
/* 4K-page alignement */
|
||||
Tables += (PG_SIZE - (int)Tables) & 0xFFF;
|
||||
|
||||
/* Reset Tables */
|
||||
memset( Tables, 0, nbTables*sizeof(page_table) );
|
||||
pageDirectory = (page_directory *) Tables;
|
||||
pageTable = (page_table *)((int)Tables + PG_SIZE);
|
||||
|
||||
nbInitPages = 0;
|
||||
directoryEntry = 0;
|
||||
tableEntry = 0;
|
||||
physPage = 0;
|
||||
|
||||
while ( nbInitPages != nbPages ){
|
||||
if ( tableEntry == 0 ){
|
||||
pageDirectory->pageDirEntry[directoryEntry].bits.page_frame_address = (unsigned int)pageTable >> 12;
|
||||
pageDirectory->pageDirEntry[directoryEntry].bits.available = 0;
|
||||
pageDirectory->pageDirEntry[directoryEntry].bits.page_size = 0;
|
||||
pageDirectory->pageDirEntry[directoryEntry].bits.accessed = 0;
|
||||
pageDirectory->pageDirEntry[directoryEntry].bits.cache_disable = 0;
|
||||
pageDirectory->pageDirEntry[directoryEntry].bits.write_through = 0;
|
||||
pageDirectory->pageDirEntry[directoryEntry].bits.user = 1;
|
||||
pageDirectory->pageDirEntry[directoryEntry].bits.writable = 1;
|
||||
pageDirectory->pageDirEntry[directoryEntry].bits.present = 1;
|
||||
}
|
||||
pageTable->pageTableEntry[tableEntry].bits.page_frame_address = physPage;
|
||||
pageTable->pageTableEntry[tableEntry].bits.available = 0;
|
||||
pageTable->pageTableEntry[tableEntry].bits.dirty = 0;
|
||||
pageTable->pageTableEntry[tableEntry].bits.accessed = 0;
|
||||
pageTable->pageTableEntry[tableEntry].bits.cache_disable = 0;
|
||||
pageTable->pageTableEntry[tableEntry].bits.write_through = 0;
|
||||
pageTable->pageTableEntry[tableEntry].bits.user = 1;
|
||||
pageTable->pageTableEntry[tableEntry].bits.writable = 1;
|
||||
pageTable->pageTableEntry[tableEntry].bits.present = 1;
|
||||
|
||||
physPage ++;
|
||||
tableEntry ++;
|
||||
|
||||
if (tableEntry >= MAX_ENTRY){
|
||||
tableEntry = 0;
|
||||
directoryEntry ++;
|
||||
pageTable ++;
|
||||
}
|
||||
|
||||
nbInitPages++;
|
||||
}
|
||||
|
||||
regCr3 &= ~(CR3_PAGE_WRITE_THROUGH);
|
||||
regCr3 &= ~(CR3_PAGE_CACHE_DISABLE);
|
||||
/*regCr3.cr3.page_directory_base = (unsigned int)pageDirectory >> 12;*/
|
||||
regCr3 = (unsigned int)pageDirectory & CR3_PAGE_DIRECTORY_MASK;
|
||||
|
||||
i386_set_cr3( regCr3 );
|
||||
|
||||
_CPU_enable_cache();
|
||||
_CPU_enable_paging();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Is cache enable
|
||||
*/
|
||||
int _CPU_is_cache_enabled(void)
|
||||
{
|
||||
unsigned int regCr0;
|
||||
|
||||
regCr0 = i386_get_cr0();
|
||||
return( ~(regCr0 & CR0_PAGE_LEVEL_CACHE_DISABLE) );
|
||||
}
|
||||
|
||||
/*
|
||||
* Is paging enable
|
||||
*/
|
||||
int _CPU_is_paging_enabled(void)
|
||||
{
|
||||
unsigned int regCr0;
|
||||
|
||||
regCr0 = i386_get_cr0();
|
||||
return(regCr0 & CR0_PAGING);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Translate the physical address in the virtual space and return
|
||||
* the translated address in mappedAddress
|
||||
*/
|
||||
|
||||
int _CPU_map_phys_address(
|
||||
void **mappedAddress,
|
||||
void *physAddress,
|
||||
int size,
|
||||
int flag
|
||||
)
|
||||
{
|
||||
page_table *localPageTable;
|
||||
unsigned int lastAddress, countAddress;
|
||||
char *Tables;
|
||||
linear_address virtualAddress;
|
||||
unsigned char pagingWasEnabled;
|
||||
|
||||
pagingWasEnabled = 0;
|
||||
|
||||
if (_CPU_is_paging_enabled()){
|
||||
pagingWasEnabled = 1;
|
||||
_CPU_disable_paging();
|
||||
}
|
||||
|
||||
countAddress = (unsigned int)physAddress;
|
||||
lastAddress = (unsigned int)physAddress + (size - 1);
|
||||
virtualAddress.address = 0;
|
||||
|
||||
while (1) {
|
||||
|
||||
if ((countAddress & ~MASK_OFFSET) > (lastAddress & ~MASK_OFFSET))
|
||||
break;
|
||||
|
||||
/* Need to allocate a new page table */
|
||||
if (pageDirectory->pageDirEntry[directoryEntry].bits.page_frame_address == 0){
|
||||
/* We allocate 2 pages to perform 4k-page alignement */
|
||||
Tables = (char *)malloc(2*sizeof(page_table));
|
||||
if ( Tables == NULL ){
|
||||
if (pagingWasEnabled)
|
||||
_CPU_enable_paging();
|
||||
return -1; /* unable to allocate memory */
|
||||
}
|
||||
/* 4K-page alignement */
|
||||
Tables += (PG_SIZE - (int)Tables) & 0xFFF;
|
||||
|
||||
/* Reset Table */
|
||||
memset( Tables, 0, sizeof(page_table) );
|
||||
pageDirectory->pageDirEntry[directoryEntry].bits.page_frame_address =
|
||||
(unsigned int)Tables >> 12;
|
||||
pageDirectory->pageDirEntry[directoryEntry].bits.available = 0;
|
||||
pageDirectory->pageDirEntry[directoryEntry].bits.page_size = 0;
|
||||
pageDirectory->pageDirEntry[directoryEntry].bits.accessed = 0;
|
||||
pageDirectory->pageDirEntry[directoryEntry].bits.cache_disable = 0;
|
||||
pageDirectory->pageDirEntry[directoryEntry].bits.write_through = 0;
|
||||
pageDirectory->pageDirEntry[directoryEntry].bits.user = 1;
|
||||
pageDirectory->pageDirEntry[directoryEntry].bits.writable = 1;
|
||||
pageDirectory->pageDirEntry[directoryEntry].bits.present = 1;
|
||||
}
|
||||
|
||||
|
||||
localPageTable = (page_table *)(pageDirectory->
|
||||
pageDirEntry[directoryEntry].bits.
|
||||
page_frame_address << 12);
|
||||
|
||||
if (virtualAddress.address == 0){
|
||||
virtualAddress.bits.directory = directoryEntry;
|
||||
virtualAddress.bits.page = tableEntry;
|
||||
virtualAddress.bits.offset = (unsigned int)physAddress & MASK_OFFSET;
|
||||
}
|
||||
|
||||
localPageTable->pageTableEntry[tableEntry].bits.page_frame_address =
|
||||
((unsigned int)countAddress & ~MASK_OFFSET) >> 12;
|
||||
localPageTable->pageTableEntry[tableEntry].bits.available = 0;
|
||||
localPageTable->pageTableEntry[tableEntry].bits.dirty = 0;
|
||||
localPageTable->pageTableEntry[tableEntry].bits.accessed = 0;
|
||||
localPageTable->pageTableEntry[tableEntry].bits.cache_disable = 0;
|
||||
localPageTable->pageTableEntry[tableEntry].bits.write_through = 0;
|
||||
localPageTable->pageTableEntry[tableEntry].bits.user = 1;
|
||||
localPageTable->pageTableEntry[tableEntry].bits.writable = 0;
|
||||
localPageTable->pageTableEntry[tableEntry].bits.present = 1;
|
||||
|
||||
localPageTable->pageTableEntry[tableEntry].table_entry |= flag ;
|
||||
|
||||
countAddress += PG_SIZE;
|
||||
tableEntry++;
|
||||
if (tableEntry >= MAX_ENTRY){
|
||||
tableEntry = 0;
|
||||
directoryEntry++;
|
||||
}
|
||||
}
|
||||
|
||||
if (mappedAddress != 0)
|
||||
*mappedAddress = (void *)(virtualAddress.address);
|
||||
if (pagingWasEnabled)
|
||||
_CPU_enable_paging();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* "Compress" the Directory and Page tables to avoid
|
||||
* important loss of address range
|
||||
*/
|
||||
static void Paging_Table_Compress(void)
|
||||
{
|
||||
unsigned int dirCount, pageCount;
|
||||
page_table *localPageTable;
|
||||
|
||||
if (tableEntry == 0){
|
||||
dirCount = directoryEntry - 1;
|
||||
pageCount = MAX_ENTRY - 1;
|
||||
}
|
||||
else {
|
||||
dirCount = directoryEntry;
|
||||
pageCount = tableEntry - 1;
|
||||
}
|
||||
|
||||
while (1){
|
||||
|
||||
localPageTable = (page_table *)(pageDirectory->
|
||||
pageDirEntry[dirCount].bits.
|
||||
page_frame_address << 12);
|
||||
|
||||
if (localPageTable->pageTableEntry[pageCount].bits.present == 1){
|
||||
pageCount++;
|
||||
if (pageCount >= MAX_ENTRY){
|
||||
pageCount = 0;
|
||||
dirCount++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if (pageCount == 0) {
|
||||
if (dirCount == 0){
|
||||
break;
|
||||
}
|
||||
else {
|
||||
pageCount = MAX_ENTRY - 1;
|
||||
dirCount-- ;
|
||||
}
|
||||
}
|
||||
else
|
||||
pageCount-- ;
|
||||
}
|
||||
|
||||
directoryEntry = dirCount;
|
||||
tableEntry = pageCount;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Unmap the virtual address from the tables
|
||||
* (we do not deallocate the table already allocated)
|
||||
*/
|
||||
|
||||
int _CPU_unmap_virt_address(
|
||||
void *mappedAddress,
|
||||
int size
|
||||
)
|
||||
{
|
||||
|
||||
linear_address linearAddr;
|
||||
page_table *localPageTable;
|
||||
unsigned int lastAddr ;
|
||||
unsigned char pagingWasEnabled;
|
||||
|
||||
pagingWasEnabled = 0;
|
||||
|
||||
if (_CPU_is_paging_enabled()){
|
||||
pagingWasEnabled = 1;
|
||||
_CPU_disable_paging();
|
||||
}
|
||||
|
||||
linearAddr.address = (unsigned int)mappedAddress;
|
||||
lastAddr = (unsigned int)mappedAddress + (size - 1);
|
||||
|
||||
while (1){
|
||||
|
||||
if ((linearAddr.address & ~MASK_OFFSET) > (lastAddr & ~MASK_OFFSET))
|
||||
break;
|
||||
|
||||
if (pageDirectory->pageDirEntry[linearAddr.bits.directory].bits.present == 0){
|
||||
if (pagingWasEnabled)
|
||||
_CPU_enable_paging();
|
||||
return -1;
|
||||
}
|
||||
|
||||
localPageTable = (page_table *)(pageDirectory->
|
||||
pageDirEntry[linearAddr.bits.directory].bits.
|
||||
page_frame_address << 12);
|
||||
|
||||
if (localPageTable->pageTableEntry[linearAddr.bits.page].bits.present == 0){
|
||||
if (pagingWasEnabled)
|
||||
_CPU_enable_paging();
|
||||
return -1;
|
||||
}
|
||||
|
||||
localPageTable->pageTableEntry[linearAddr.bits.page].bits.present = 0;
|
||||
|
||||
linearAddr.address += PG_SIZE ;
|
||||
}
|
||||
Paging_Table_Compress();
|
||||
if (pagingWasEnabled)
|
||||
_CPU_enable_paging();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Modify the flags PRESENT, WRITABLE, USER, WRITE_TROUGH, CACHE_DISABLE
|
||||
* of the page's descriptor.
|
||||
*/
|
||||
|
||||
int _CPU_change_memory_mapping_attribute(
|
||||
void **newAddress,
|
||||
void *mappedAddress,
|
||||
unsigned int size,
|
||||
unsigned int flag
|
||||
)
|
||||
{
|
||||
|
||||
linear_address linearAddr;
|
||||
page_table *localPageTable;
|
||||
unsigned int lastAddr ;
|
||||
unsigned char pagingWasEnabled;
|
||||
|
||||
pagingWasEnabled = 0;
|
||||
|
||||
if (_CPU_is_paging_enabled()){
|
||||
pagingWasEnabled = 1;
|
||||
_CPU_disable_paging();
|
||||
}
|
||||
|
||||
linearAddr.address = (unsigned int)mappedAddress;
|
||||
lastAddr = (unsigned int)mappedAddress + (size - 1);
|
||||
|
||||
while (1){
|
||||
|
||||
if ((linearAddr.address & ~MASK_OFFSET) > (lastAddr & ~MASK_OFFSET))
|
||||
break;
|
||||
|
||||
if (pageDirectory->pageDirEntry[linearAddr.bits.directory].bits.present == 0){
|
||||
if (pagingWasEnabled)
|
||||
_CPU_enable_paging();
|
||||
return -1;
|
||||
}
|
||||
localPageTable = (page_table *)(pageDirectory->
|
||||
pageDirEntry[linearAddr.bits.directory].bits.
|
||||
page_frame_address << 12);
|
||||
|
||||
if (localPageTable->pageTableEntry[linearAddr.bits.page].bits.present == 0){
|
||||
if (pagingWasEnabled)
|
||||
_CPU_enable_paging();
|
||||
return -1;
|
||||
}
|
||||
|
||||
localPageTable->pageTableEntry[linearAddr.bits.page].table_entry &= ~MASK_FLAGS ;
|
||||
localPageTable->pageTableEntry[linearAddr.bits.page].table_entry |= flag ;
|
||||
|
||||
linearAddr.address += PG_SIZE ;
|
||||
}
|
||||
|
||||
if (newAddress != NULL)
|
||||
*newAddress = mappedAddress ;
|
||||
|
||||
if (pagingWasEnabled)
|
||||
_CPU_enable_paging();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Display the page descriptor flags
|
||||
* CACHE_DISABLE of the whole memory
|
||||
*/
|
||||
|
||||
#include <rtems/bspIo.h>
|
||||
|
||||
int _CPU_display_memory_attribute(void)
|
||||
{
|
||||
unsigned int dirCount, pageCount;
|
||||
unsigned int regCr0;
|
||||
page_table *localPageTable;
|
||||
unsigned int prevCache;
|
||||
unsigned int prevPresent;
|
||||
unsigned int maxPage;
|
||||
unsigned char pagingWasEnabled;
|
||||
|
||||
regCr0 = i386_get_cr0();
|
||||
|
||||
printk("\n\n********* MEMORY CACHE CONFIGURATION *****\n");
|
||||
|
||||
printk("CR0 -> paging : %s\n",((regCr0 & CR0_PAGING) ? "ENABLE ":"DISABLE"));
|
||||
printk(" page-level cache : %s\n\n",((regCr0 & CR0_PAGE_LEVEL_CACHE_DISABLE) ? "DISABLE":"ENABLE"));
|
||||
|
||||
if ((regCr0 & CR0_PAGING) == 0)
|
||||
return 0;
|
||||
|
||||
prevPresent = 0;
|
||||
prevCache = 1;
|
||||
|
||||
pagingWasEnabled = 0;
|
||||
|
||||
if (_CPU_is_paging_enabled()){
|
||||
pagingWasEnabled = 1;
|
||||
_CPU_disable_paging();
|
||||
}
|
||||
|
||||
for (dirCount = 0; dirCount < directoryEntry+1; dirCount++) {
|
||||
|
||||
localPageTable = (page_table *)(pageDirectory->
|
||||
pageDirEntry[dirCount].bits.
|
||||
page_frame_address << 12);
|
||||
|
||||
maxPage = MAX_ENTRY;
|
||||
/*if ( dirCount == (directoryEntry-1))
|
||||
maxPage = tableEntry;*/
|
||||
for (pageCount = 0; pageCount < maxPage; pageCount++) {
|
||||
|
||||
if (localPageTable->pageTableEntry[pageCount].bits.present != 0){
|
||||
if (prevPresent == 0){
|
||||
prevPresent = 1;
|
||||
printk ("present page from address %x \n", ((dirCount << 22)|(pageCount << 12)));
|
||||
}
|
||||
if (prevCache != localPageTable->pageTableEntry[pageCount].bits.cache_disable ) {
|
||||
prevCache = localPageTable->pageTableEntry[pageCount].
|
||||
bits.cache_disable;
|
||||
printk (" cache %s from %x <phy %x>\n",
|
||||
(prevCache ? "DISABLE" : "ENABLE "),
|
||||
((dirCount << 22)|(pageCount << 12)),
|
||||
localPageTable->pageTableEntry[pageCount].bits.page_frame_address << 12);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (prevPresent == 1){
|
||||
prevPresent = 0;
|
||||
printk ("Absent from %x \n", ((dirCount << 22)|(pageCount << 12)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (pagingWasEnabled)
|
||||
_CPU_enable_paging();
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user