kernel: facility for user-visible memory
. map all objects named usermapped_*.o with globally visible pages; usermapped_glo_*.o with the VM 'global' bit on, i.e. permanently in tlb (very scarce resource!) . added kinfo, machine, kmessages and loadinfo for a start . modified log, tty to make use of the shared messages struct
This commit is contained in:
@@ -6,7 +6,7 @@ PROG= kernel
|
||||
.include "arch/${MACHINE_ARCH}/Makefile.inc"
|
||||
|
||||
SRCS+= clock.c cpulocals.c interrupt.c main.c proc.c system.c \
|
||||
table.c utility.c
|
||||
table.c utility.c usermapped_data.c
|
||||
|
||||
LINKERSCRIPT=${.CURDIR}/arch/${MACHINE_ARCH}/kernel.lds
|
||||
|
||||
|
||||
@@ -182,6 +182,11 @@ void arch_proc_reset(struct proc *pr)
|
||||
pr->p_reg.ds = USER_DS_SELECTOR;
|
||||
}
|
||||
|
||||
void arch_set_secondary_ipc_return(struct proc *p, u32_t val)
|
||||
{
|
||||
p->p_reg.bx = val;
|
||||
}
|
||||
|
||||
int restore_fpu(struct proc *pr)
|
||||
{
|
||||
int failed;
|
||||
|
||||
@@ -21,8 +21,14 @@ SECTIONS
|
||||
|
||||
. += _kern_offset;
|
||||
|
||||
. = ALIGN(4096); usermapped_start = .;
|
||||
.usermapped_glo : AT(ADDR(.usermapped_glo) - _kern_offset) { usermapped_glo*.o }
|
||||
. = ALIGN(4096); usermapped_nonglo_start = .;
|
||||
.usermapped : AT(ADDR(.usermapped) - _kern_offset) { usermapped_*.o }
|
||||
. = ALIGN(4096); usermapped_end = .;
|
||||
.text : AT(ADDR(.text) - _kern_offset) { *(.text*) }
|
||||
.data ALIGN(4096) : AT(ADDR(.data) - _kern_offset) { *(.data .rodata* ) }
|
||||
. = ALIGN(4096);
|
||||
.bss ALIGN(4096) : AT(ADDR(.bss) - _kern_offset) { *(.bss* COMMON)
|
||||
__k_unpaged__kern_size = . - _kern_vir_base;
|
||||
_kern_size = __k_unpaged__kern_size;
|
||||
|
||||
@@ -757,10 +757,14 @@ static int oxpcie_mapping_index = -1,
|
||||
lapic_mapping_index = -1,
|
||||
ioapic_first_index = -1,
|
||||
ioapic_last_index = -1,
|
||||
video_mem_mapping_index = -1;
|
||||
video_mem_mapping_index = -1,
|
||||
usermapped_glo_index = -1,
|
||||
usermapped_index = -1, first_um_idx = -1;
|
||||
|
||||
extern char *video_mem;
|
||||
|
||||
extern char usermapped_start, usermapped_end, usermapped_nonglo_start;
|
||||
|
||||
int arch_phys_map(const int index,
|
||||
phys_bytes *addr,
|
||||
phys_bytes *len,
|
||||
@@ -769,9 +773,19 @@ int arch_phys_map(const int index,
|
||||
static int first = 1;
|
||||
int freeidx = 0;
|
||||
static char *ser_var = NULL;
|
||||
u32_t glo_len = (u32_t) &usermapped_nonglo_start -
|
||||
(u32_t) &usermapped_start;
|
||||
|
||||
if(first) {
|
||||
video_mem_mapping_index = freeidx++;
|
||||
if(glo_len > 0) {
|
||||
usermapped_glo_index = freeidx++;
|
||||
}
|
||||
|
||||
usermapped_index = freeidx++;
|
||||
first_um_idx = usermapped_index;
|
||||
if(usermapped_glo_index != -1)
|
||||
first_um_idx = usermapped_glo_index;
|
||||
|
||||
#ifdef USE_APIC
|
||||
if(lapic_addr)
|
||||
@@ -798,21 +812,34 @@ int arch_phys_map(const int index,
|
||||
first = 0;
|
||||
}
|
||||
|
||||
#ifdef USE_APIC
|
||||
if (index == video_mem_mapping_index) {
|
||||
if(index == usermapped_glo_index) {
|
||||
*addr = vir2phys(&usermapped_start);
|
||||
*len = glo_len;
|
||||
*flags = VMMF_USER | VMMF_GLO;
|
||||
return OK;
|
||||
}
|
||||
else if(index == usermapped_index) {
|
||||
*addr = vir2phys(&usermapped_nonglo_start);
|
||||
*len = (u32_t) &usermapped_end -
|
||||
(u32_t) &usermapped_nonglo_start;
|
||||
*flags = VMMF_USER;
|
||||
return OK;
|
||||
}
|
||||
else if (index == video_mem_mapping_index) {
|
||||
/* map video memory in so we can print panic messages */
|
||||
*addr = MULTIBOOT_VIDEO_BUFFER;
|
||||
*len = I386_PAGE_SIZE;
|
||||
*flags = 0;
|
||||
*flags = VMMF_WRITE;
|
||||
return OK;
|
||||
}
|
||||
#ifdef USE_APIC
|
||||
else if (index == lapic_mapping_index) {
|
||||
/* map the local APIC if enabled */
|
||||
if (!lapic_addr)
|
||||
return EINVAL;
|
||||
*addr = lapic_addr;
|
||||
*len = 4 << 10 /* 4kB */;
|
||||
*flags = VMMF_UNCACHED;
|
||||
*flags = VMMF_UNCACHED | VMMF_WRITE;
|
||||
return OK;
|
||||
}
|
||||
else if (ioapic_enabled && index >= ioapic_first_index && index <= ioapic_last_index) {
|
||||
@@ -820,7 +847,7 @@ int arch_phys_map(const int index,
|
||||
*addr = io_apic[ioapic_idx].paddr;
|
||||
assert(*addr);
|
||||
*len = 4 << 10 /* 4kB */;
|
||||
*flags = VMMF_UNCACHED;
|
||||
*flags = VMMF_UNCACHED | VMMF_WRITE;
|
||||
printf("ioapic map: addr 0x%lx\n", *addr);
|
||||
return OK;
|
||||
}
|
||||
@@ -830,7 +857,7 @@ int arch_phys_map(const int index,
|
||||
if(index == oxpcie_mapping_index) {
|
||||
*addr = strtoul(ser_var+2, NULL, 16);
|
||||
*len = 0x4000;
|
||||
*flags = VMMF_UNCACHED;
|
||||
*flags = VMMF_UNCACHED | VMMF_WRITE;
|
||||
return OK;
|
||||
}
|
||||
#endif
|
||||
@@ -860,6 +887,31 @@ int arch_phys_map_reply(const int index, const vir_bytes addr)
|
||||
return OK;
|
||||
}
|
||||
#endif
|
||||
if(index == first_um_idx) {
|
||||
u32_t usermapped_offset;
|
||||
assert(addr > (u32_t) &usermapped_start);
|
||||
usermapped_offset = addr - (u32_t) &usermapped_start;
|
||||
memset(&minix_kerninfo, 0, sizeof(minix_kerninfo));
|
||||
#define FIXEDPTR(ptr) (void *) ((u32_t)ptr + usermapped_offset)
|
||||
#define FIXPTR(ptr) ptr = FIXEDPTR(ptr)
|
||||
#define ASSIGN(minixstruct) minix_kerninfo.minixstruct = FIXEDPTR(&minixstruct)
|
||||
ASSIGN(kinfo);
|
||||
ASSIGN(machine);
|
||||
ASSIGN(kmessages);
|
||||
ASSIGN(loadinfo);
|
||||
|
||||
/* adjust the pointers of the functions and the struct
|
||||
* itself to the user-accessible mapping
|
||||
*/
|
||||
minix_kerninfo.kerninfo_magic = KERNINFO_MAGIC;
|
||||
minix_kerninfo.minix_feature_flags = minix_feature_flags;
|
||||
minix_kerninfo_user = (vir_bytes) FIXEDPTR(&minix_kerninfo);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
if(index == usermapped_index) return OK;
|
||||
|
||||
if (index == video_mem_mapping_index) {
|
||||
video_mem_vaddr = addr;
|
||||
return OK;
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
|
||||
/* to-be-built kinfo struct, diagnostics buffer */
|
||||
kinfo_t kinfo;
|
||||
struct kmessages kmess;
|
||||
struct kmessages kmessages;
|
||||
|
||||
/* pg_utils.c uses this; in this phase, there is a 1:1 mapping. */
|
||||
phys_bytes vir2phys(void *addr) { return (phys_bytes) addr; }
|
||||
|
||||
17
kernel/glo.h
17
kernel/glo.h
@@ -19,11 +19,18 @@
|
||||
#include "debug.h"
|
||||
|
||||
/* Kernel information structures. This groups vital kernel information. */
|
||||
EXTERN struct kinfo kinfo; /* kernel information for users */
|
||||
EXTERN struct machine machine; /* machine information for users */
|
||||
EXTERN struct kmessages kmess; /* diagnostic messages in kernel */
|
||||
EXTERN struct k_randomness krandom; /* gather kernel random information */
|
||||
EXTERN struct loadinfo kloadinfo; /* status of load average */
|
||||
extern struct kinfo kinfo; /* kernel information for users */
|
||||
extern struct machine machine; /* machine information for users */
|
||||
extern struct kmessages kmessages; /* diagnostic messages in kernel */
|
||||
extern struct loadinfo loadinfo; /* status of load average */
|
||||
extern struct minix_kerninfo minix_kerninfo;
|
||||
|
||||
EXTERN struct k_randomness krandom; /* gather kernel random information */
|
||||
|
||||
vir_bytes minix_kerninfo_user;
|
||||
|
||||
#define kmess kmessages
|
||||
#define kloadinfo loadinfo
|
||||
|
||||
/* Process scheduling information and the kernel reentry count. */
|
||||
EXTERN struct proc *vmrequest; /* first process on vmrequest queue */
|
||||
|
||||
@@ -608,6 +608,16 @@ int do_ipc(reg_t r1, reg_t r2, reg_t r3)
|
||||
return EDOM;
|
||||
return mini_senda(caller_ptr, (asynmsg_t *) r3, msg_size);
|
||||
}
|
||||
case MINIX_KERNINFO:
|
||||
{
|
||||
/* It might not be initialized yet. */
|
||||
if(!minix_kerninfo_user) {
|
||||
return EBADCALL;
|
||||
}
|
||||
|
||||
arch_set_secondary_ipc_return(caller_ptr, minix_kerninfo_user);
|
||||
return OK;
|
||||
}
|
||||
default:
|
||||
return EBADCALL; /* illegal system call */
|
||||
}
|
||||
|
||||
@@ -150,6 +150,7 @@ void stop_profile_clock(void);
|
||||
/* functions defined in architecture-dependent files. */
|
||||
void prot_init();
|
||||
void arch_post_init();
|
||||
void arch_set_secondary_ipc_return(struct proc *, u32_t val);
|
||||
phys_bytes phys_copy(phys_bytes source, phys_bytes dest, phys_bytes
|
||||
count);
|
||||
void phys_copy_fault(void);
|
||||
|
||||
@@ -167,11 +167,6 @@ int do_getinfo(struct proc * caller, message * m_ptr)
|
||||
|
||||
break;
|
||||
}
|
||||
case GET_KMESSAGES: {
|
||||
length = sizeof(struct kmessages);
|
||||
src_vir = (vir_bytes) &kmess;
|
||||
break;
|
||||
}
|
||||
case GET_IRQACTIDS: {
|
||||
length = sizeof(irq_actids);
|
||||
src_vir = (vir_bytes) irq_actids;
|
||||
|
||||
11
kernel/usermapped_data.c
Normal file
11
kernel/usermapped_data.c
Normal file
@@ -0,0 +1,11 @@
|
||||
#include "kernel.h"
|
||||
|
||||
/* This is the user-visible struct that has pointers to other bits of data. */
|
||||
struct minix_kerninfo minix_kerninfo;
|
||||
|
||||
/* Kernel information structures. */
|
||||
struct kinfo kinfo; /* kernel information for users */
|
||||
struct machine machine; /* machine information for users */
|
||||
struct kmessages kmessages; /* diagnostic messages in kernel */
|
||||
struct loadinfo loadinfo; /* status of load average */
|
||||
|
||||
Reference in New Issue
Block a user