Library call for cpu features; make kernel and vm use this to query cpu
features (specifically: 4MB pages and TLB global bit). Only enable these features in CR4 if available. 4MB pages to be used in the near future.
This commit is contained in:
parent
d0b6e76bfb
commit
bdab3c4cfb
10 changed files with 134 additions and 13 deletions
10
include/minix/cpufeature.h
Normal file
10
include/minix/cpufeature.h
Normal file
|
@ -0,0 +1,10 @@
|
|||
|
||||
#ifndef _MINIX_CPUFEATURE_H
|
||||
#define _MINIX_CPUFEATURE_H 1
|
||||
|
||||
#define _CPUF_I386_PSE 1 /* Page Size Extension */
|
||||
#define _CPUF_I386_PGE 2 /* Page Global Enable */
|
||||
|
||||
_PROTOTYPE(int _cpufeature, (int featureno));
|
||||
|
||||
#endif
|
|
@ -15,6 +15,7 @@ _PROTOTYPE(void std_err, (char *_s));
|
|||
_PROTOTYPE(void prints, (const char *_s, ...));
|
||||
_PROTOTYPE(int fsversion, (char *_dev, char *_prog));
|
||||
_PROTOTYPE(int getprocessor, (void));
|
||||
_PROTOTYPE(int _cpuid, (u32_t eax_in, u32_t *eax, u32_t *ebx, u32_t *ecx, u32_t *edx));
|
||||
_PROTOTYPE(int load_mtab, (char *_prog_name));
|
||||
_PROTOTYPE(int rewrite_mtab, (char *_prog_name));
|
||||
_PROTOTYPE(int get_mtab_entry, (char *_s1, char *_s2, char *_s3, char *_s4));
|
||||
|
|
|
@ -58,3 +58,7 @@ sys/vm_i386.h
|
|||
*/
|
||||
#define I386_VM_PFE_W 0x02 /* Caused by write (otherwise read) */
|
||||
#define I386_VM_PFE_U 0x04 /* CPU in user mode (otherwise supervisor) */
|
||||
|
||||
/* CPUID flags */
|
||||
#define CPUID1_EDX_PSE (1L << 3) /* Page Size Extension */
|
||||
#define CPUID1_EDX_PGE (1L << 13) /* Page Global (bit) Enable */
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include <minix/type.h>
|
||||
#include <minix/syslib.h>
|
||||
#include <minix/sysutil.h>
|
||||
#include <minix/cpufeature.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <sys/vm_i386.h>
|
||||
|
@ -155,7 +156,10 @@ PRIVATE void set_cr3()
|
|||
PRIVATE void vm_enable_paging(void)
|
||||
{
|
||||
u32_t cr0, cr4;
|
||||
int psok, pgeok;
|
||||
|
||||
psok = _cpufeature(_CPUF_I386_PSE);
|
||||
pgeok = _cpufeature(_CPUF_I386_PGE);
|
||||
|
||||
cr0= read_cr0();
|
||||
cr4= read_cr4();
|
||||
|
@ -169,7 +173,14 @@ PRIVATE void vm_enable_paging(void)
|
|||
|
||||
/* First enable paging, then enable global page flag. */
|
||||
write_cr0(cr0 | I386_CR0_PG);
|
||||
write_cr4(cr4 | I386_CR4_PGE);
|
||||
|
||||
/* May we enable these features? */
|
||||
if(pgeok)
|
||||
cr4 |= I386_CR4_PGE;
|
||||
if(psok)
|
||||
cr4 |= I386_CR4_PSE;
|
||||
|
||||
write_cr4(cr4);
|
||||
}
|
||||
|
||||
PUBLIC vir_bytes alloc_remote_segment(u32_t *selector,
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
#define DEBUG_TIME_LOCKS 1
|
||||
|
||||
/* Runtime sanity checking. */
|
||||
#define DEBUG_VMASSERT 0
|
||||
#define DEBUG_VMASSERT 1
|
||||
#define DEBUG_SCHED_CHECK 0
|
||||
|
||||
#endif /* DEBUG_H */
|
||||
|
|
|
@ -6,6 +6,7 @@ LIBRARIES=libc
|
|||
|
||||
libc_FILES=" \
|
||||
_cpuid.s \
|
||||
_cpufeature.c \
|
||||
alloca.s \
|
||||
get_bp.s \
|
||||
getprocessor.s \
|
||||
|
|
34
lib/i386/misc/_cpufeature.c
Normal file
34
lib/i386/misc/_cpufeature.c
Normal file
|
@ -0,0 +1,34 @@
|
|||
|
||||
#include <stdint.h>
|
||||
#include <minix/minlib.h>
|
||||
#include <minix/cpufeature.h>
|
||||
#include <sys/vm_i386.h>
|
||||
|
||||
int _cpufeature(int cpufeature)
|
||||
{
|
||||
u32_t cpuid_feature_edx = 0;
|
||||
int proc;
|
||||
|
||||
proc = getprocessor();
|
||||
|
||||
/* If processor supports CPUID and its CPUID supports enough
|
||||
* parameters, retrieve EDX feature flags to test against.
|
||||
*/
|
||||
if(proc >= 586) {
|
||||
u32_t params, a, b, c, d;
|
||||
_cpuid(0, ¶ms, &b, &c, &d);
|
||||
if(params > 0) {
|
||||
_cpuid(1, &a, &b, &c, &cpuid_feature_edx);
|
||||
}
|
||||
}
|
||||
|
||||
switch(cpufeature) {
|
||||
case _CPUF_I386_PSE:
|
||||
return cpuid_feature_edx & CPUID1_EDX_PSE;
|
||||
case _CPUF_I386_PGE:
|
||||
return cpuid_feature_edx & CPUID1_EDX_PGE;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -16,6 +16,7 @@
|
|||
#include <minix/sysutil.h>
|
||||
#include <minix/syslib.h>
|
||||
#include <minix/safecopies.h>
|
||||
#include <minix/cpufeature.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
|
@ -33,6 +34,9 @@
|
|||
|
||||
#include "memory.h"
|
||||
|
||||
int global_bit_ok = 0;
|
||||
int bigpage_ok = 0;
|
||||
|
||||
/* Location in our virtual address space where we can map in
|
||||
* any physical page we want.
|
||||
*/
|
||||
|
@ -70,6 +74,9 @@ static struct {
|
|||
/* Nevertheless, introduce these macros to make the code readable. */
|
||||
#define CLICK2PAGE(c) ((c) / CLICKSPERPAGE)
|
||||
|
||||
/* Page table that contains pointers to all page directories. */
|
||||
u32_t page_directories_phys, *page_directories = NULL;
|
||||
|
||||
#if SANITYCHECKS
|
||||
#define PT_SANE(p) { pt_sanitycheck((p), __FILE__, __LINE__); SANITYCHECK(SCL_DETAIL); }
|
||||
/*===========================================================================*
|
||||
|
@ -507,7 +514,10 @@ PUBLIC void pt_init(void)
|
|||
phys_bytes lo, hi;
|
||||
vir_bytes extra_clicks;
|
||||
u32_t moveup = 0;
|
||||
|
||||
|
||||
global_bit_ok = _cpufeature(_CPUF_I386_PGE);
|
||||
bigpage_ok = _cpufeature(_CPUF_I386_PSE);
|
||||
|
||||
/* Shorthand. */
|
||||
newpt = &vmp->vm_pt;
|
||||
|
||||
|
@ -567,6 +577,15 @@ PUBLIC void pt_init(void)
|
|||
/* Map in kernel. */
|
||||
if(pt_mapkernel(newpt) != OK)
|
||||
vm_panic("pt_init: pt_mapkernel failed", NO_NUM);
|
||||
|
||||
#if 0
|
||||
/* Allocate us a page table in which to remember page directory
|
||||
* pointers.
|
||||
*/
|
||||
if(!(page_directories = vm_allocpages(&page_directories_phys,
|
||||
1, VMP_PAGETABLE)))
|
||||
vm_panic("no virt addr for vm mappings", NO_NUM);
|
||||
#endif
|
||||
|
||||
/* Give our process the new, copied, private page table. */
|
||||
pt_bind(newpt, vmp);
|
||||
|
@ -627,10 +646,23 @@ PUBLIC void pt_init(void)
|
|||
*===========================================================================*/
|
||||
PUBLIC int pt_bind(pt_t *pt, struct vmproc *who)
|
||||
{
|
||||
int slot;
|
||||
|
||||
/* Basic sanity checks. */
|
||||
vm_assert(who);
|
||||
vm_assert(who->vm_flags & VMF_INUSE);
|
||||
if(pt) PT_SANE(pt);
|
||||
vm_assert(pt);
|
||||
|
||||
#if 0
|
||||
slot = who->vm_slot;
|
||||
vm_assert(slot >= 0);
|
||||
vm_assert(slot < ELEMENTS(vmproc));
|
||||
vm_assert(!(pt->pt_dir_phys & ~I386_VM_ADDR_MASK));
|
||||
|
||||
page_directories[slot] = (pt->pt_dir_phys & I386_VM_ADDR_MASK) |
|
||||
(I386_VM_PRESENT|I386_VM_WRITE);
|
||||
#endif
|
||||
|
||||
/* Tell kernel about new page table root. */
|
||||
return sys_vmctl(who->vm_endpoint, VMCTL_I386_SETCR3,
|
||||
|
@ -673,18 +705,31 @@ PUBLIC void pt_free(pt_t *pt)
|
|||
PUBLIC int pt_mapkernel(pt_t *pt)
|
||||
{
|
||||
int r;
|
||||
static int pde = -1;
|
||||
int global;
|
||||
|
||||
if(global_bit_ok) global = I386_VM_GLOBAL;
|
||||
|
||||
/* Any i386 page table needs to map in the kernel address space. */
|
||||
vm_assert(vmproc[VMP_SYSTEM].vm_flags & VMF_INUSE);
|
||||
|
||||
if(pde == -1) {
|
||||
int pde1, pde2;
|
||||
pde1 = I386_VM_PDE(KERNEL_TEXT);
|
||||
pde2 = I386_VM_PDE(KERNEL_DATA+KERNEL_DATA_LEN);
|
||||
vm_assert(pde1 == pde2);
|
||||
pde = pde1;
|
||||
vm_assert(pde >= 0);
|
||||
}
|
||||
|
||||
/* Map in text. flags: don't write, supervisor only */
|
||||
if((r=pt_writemap(pt, KERNEL_TEXT, KERNEL_TEXT, KERNEL_TEXT_LEN,
|
||||
I386_VM_PRESENT|I386_VM_GLOBAL, 0)) != OK)
|
||||
I386_VM_PRESENT|global, 0)) != OK)
|
||||
return r;
|
||||
|
||||
/* Map in data. flags: read-write, supervisor only */
|
||||
if((r=pt_writemap(pt, KERNEL_DATA, KERNEL_DATA, KERNEL_DATA_LEN,
|
||||
I386_VM_PRESENT|I386_VM_WRITE|I386_VM_GLOBAL, 0)) != OK)
|
||||
I386_VM_PRESENT|I386_VM_WRITE|global, 0)) != OK)
|
||||
return r;
|
||||
|
||||
return OK;
|
||||
|
@ -739,17 +784,25 @@ PUBLIC void pt_cycle(void)
|
|||
#define MAPFLAGS WMF_OVERWRITE
|
||||
#endif
|
||||
|
||||
static u32_t ismapped = MAP_NONE;
|
||||
|
||||
#define PHYS_MAP(a, o) \
|
||||
{ int r; \
|
||||
u32_t wipeme = (u32_t) varmap; \
|
||||
u32_t wantmapped; \
|
||||
vm_assert(varmap); \
|
||||
(o) = (a) % I386_PAGE_SIZE; \
|
||||
r = pt_writemap(&vmp->vm_pt, (vir_bytes) varmap_loc, (a) - (o), I386_PAGE_SIZE, \
|
||||
I386_VM_PRESENT | I386_VM_USER | I386_VM_WRITE, MAPFLAGS); \
|
||||
if(r != OK) \
|
||||
vm_panic("PHYS_MAP: pt_writemap failed", NO_NUM); \
|
||||
/* pt_bind() flushes TLB. */ \
|
||||
pt_bind(&vmp->vm_pt, vmp); \
|
||||
wantmapped = (a) - (o); \
|
||||
if(wantmapped != ismapped || ismapped == MAP_NONE) { \
|
||||
r = pt_writemap(&vmp->vm_pt, (vir_bytes) varmap_loc, \
|
||||
wantmapped, I386_PAGE_SIZE, \
|
||||
I386_VM_PRESENT | I386_VM_USER | I386_VM_WRITE, \
|
||||
MAPFLAGS); \
|
||||
if(r != OK) \
|
||||
vm_panic("PHYS_MAP: pt_writemap", NO_NUM); \
|
||||
ismapped = wantmapped; \
|
||||
/* pt_bind() flushes TLB. */ \
|
||||
pt_bind(&vmp->vm_pt, vmp); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define PHYSMAGIC 0x7b9a0590
|
||||
|
@ -758,6 +811,7 @@ PUBLIC void pt_cycle(void)
|
|||
#define PHYS_UNMAP if(OK != pt_writemap(&vmp->vm_pt, varmap_loc, MAP_NONE,\
|
||||
I386_PAGE_SIZE, 0, WMF_OVERWRITE)) { \
|
||||
vm_panic("PHYS_UNMAP: pt_writemap failed", NO_NUM); }
|
||||
ismapped = MAP_NONE;
|
||||
#endif
|
||||
|
||||
#define PHYS_VAL(o) (* (phys_bytes *) (varmap + (o)))
|
||||
|
|
|
@ -176,7 +176,7 @@ PUBLIC int main(void)
|
|||
*===========================================================================*/
|
||||
PRIVATE void vm_init(void)
|
||||
{
|
||||
int s;
|
||||
int s, i;
|
||||
struct memory mem_chunks[NR_MEMS];
|
||||
struct boot_image image[NR_BOOT_PROCS];
|
||||
struct boot_image *ip;
|
||||
|
@ -194,6 +194,10 @@ PRIVATE void vm_init(void)
|
|||
/* Set table to 0. This invalidates all slots (clear VMF_INUSE). */
|
||||
memset(vmproc, 0, sizeof(vmproc));
|
||||
|
||||
for(i = 0; i < ELEMENTS(vmproc); i++) {
|
||||
vmproc[i].vm_slot = i;
|
||||
}
|
||||
|
||||
/* Walk through boot-time system processes that are alive
|
||||
* now and make valid slot entries for them.
|
||||
*/
|
||||
|
|
|
@ -37,6 +37,8 @@ struct vmproc {
|
|||
callback_t vm_callback; /* function to call on vfs reply */
|
||||
int vm_callback_type; /* expected message type */
|
||||
|
||||
int vm_slot; /* process table slot */
|
||||
|
||||
union {
|
||||
struct {
|
||||
cp_grant_id_t gid;
|
||||
|
|
Loading…
Reference in a new issue