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
									
								
								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); }
 | 
			
		||||
/*===========================================================================*
 | 
			
		||||
@ -508,6 +515,9 @@ PUBLIC void pt_init(void)
 | 
			
		||||
        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;
 | 
			
		||||
 | 
			
		||||
@ -568,6 +578,15 @@ PUBLIC void pt_init(void)
 | 
			
		||||
        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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user