#include "log.h"
+#include <assert.h>
+
+extern struct minix_kerninfo *_minix_kerninfo;
+
/*==========================================================================*
* do_new_kmess *
*==========================================================================*/
void do_new_kmess(void)
{
/* Notification for a new kernel message. */
- static struct kmessages kmess; /* entire kmess structure */
+ static struct kmessages *kmess; /* entire kmess structure */
static char print_buf[_KMESS_BUF_SIZE]; /* copy new message here */
int bytes;
int i, r;
static int prev_next = 0;
- /* Try to get a fresh copy of the buffer with kernel messages. */
- if ((r=sys_getkmessages(&kmess)) != OK) {
- printf("log: couldn't get copy of kmessages: %d\n", r);
- return;
- }
+ assert(_minix_kerninfo);
+ kmess = _minix_kerninfo->kmessages;
/* Print only the new part. Determine how many new bytes there are with
* help of the current and previous 'next' index. Note that the kernel
* are new data; else we miss % KMESS_BUF_SIZE here.
* Check for size being positive, the buffer might as well be emptied!
*/
- if (kmess.km_size > 0) {
- bytes = ((kmess.km_next + _KMESS_BUF_SIZE) - prev_next) %
+ if (kmess->km_size > 0) {
+ bytes = ((kmess->km_next + _KMESS_BUF_SIZE) - prev_next) %
_KMESS_BUF_SIZE;
r= prev_next; /* start at previous old */
i=0;
while (bytes > 0) {
- print_buf[i] = kmess.km_buf[(r%_KMESS_BUF_SIZE)];
+ print_buf[i] = kmess->km_buf[(r%_KMESS_BUF_SIZE)];
bytes --;
r ++;
i ++;
/* Almost done, store 'next' so that we can determine what part of the
* kernel messages buffer to print next time a notification arrives.
*/
- prev_next = kmess.km_next;
+ prev_next = kmess->km_next;
}
#include <minix/drivers.h>
#include <termios.h>
+#include <assert.h>
#include <sys/ioctl.h>
#include <sys/vm.h>
#include <sys/video.h>
cons_ioctl(tp, 0);
}
+extern struct minix_kerninfo *_minix_kerninfo;
+
/*===========================================================================*
* do_new_kmess *
*===========================================================================*/
void do_new_kmess()
{
/* Notification for a new kernel message. */
- static struct kmessages kmess; /* kmessages structure */
+ struct kmessages *kmess_ptr; /* kmessages structure */
static int prev_next = 0; /* previous next seen */
int bytes;
int r;
- /* Try to get a fresh copy of the buffer with kernel messages. */
-#if DEAD_CODE
- /* During shutdown, the reply is garbled because new notifications arrive
- * while the system task makes a copy of the kernel messages buffer.
- * Hence, don't check the return value.
- */
- if ((r=sys_getkmessages(&kmess)) != OK) {
- printf("TTY: couldn't get copy of kmessages: %d, 0x%x\n", r,r);
- return;
- }
-#endif
- sys_getkmessages(&kmess);
+ assert(_minix_kerninfo);
+ kmess_ptr = _minix_kerninfo->kmessages;
/* Print only the new part. Determine how many new bytes there are with
* help of the current and previous 'next' index. Note that the kernel
* is new data; else we miss % _KMESS_BUF_SIZE here.
* Check for size being positive, the buffer might as well be emptied!
*/
- if (kmess.km_size > 0) {
- bytes = ((kmess.km_next + _KMESS_BUF_SIZE) - prev_next) % _KMESS_BUF_SIZE;
+ if (kmess_ptr->km_size > 0) {
+ bytes = ((kmess_ptr->km_next + _KMESS_BUF_SIZE) - prev_next) % _KMESS_BUF_SIZE;
r=prev_next; /* start at previous old */
while (bytes > 0) {
- cons_putk( kmess.km_buf[(r%_KMESS_BUF_SIZE)] );
+ cons_putk( kmess_ptr->km_buf[(r%_KMESS_BUF_SIZE)] );
bytes --;
r ++;
}
/* Almost done, store 'next' so that we can determine what part of the
* kernel messages buffer to print next time a notification arrives.
*/
- prev_next = kmess.km_next;
+ prev_next = kmess_ptr->km_next;
}
/*===========================================================================*
# define GET_MONPARAMS 4 /* get monitor parameters */
# define GET_KENV 5 /* get kernel environment string */
# define GET_IRQHOOKS 6 /* get the IRQ table */
-# define GET_KMESSAGES 7 /* get kernel messages */
# define GET_PRIVTAB 8 /* get kernel privileges table */
# define GET_KADDRESSES 9 /* get various kernel addresses */
# define GET_SCHEDINFO 10 /* get scheduling queues */
#define SVMCTL_MAP_PHYS_LEN m2_l2
#define VMMF_UNCACHED (1L << 0)
+#define VMMF_USER (1L << 1)
+#define VMMF_WRITE (1L << 2)
+#define VMMF_GLO (1L << 3)
/* Values for SVMCTL_PARAM. */
#define VMCTL_CLEAR_PAGEFAULT 12
int send(endpoint_t dest, message *m_ptr);
int sendnb(endpoint_t dest, message *m_ptr);
int senda(asynmsg_t *table, size_t count);
+int _minix_kernel_info_struct(struct minix_kerninfo **);
int _do_kernel_call(message *m_ptr);
#define SENDREC 3 /* SEND + RECEIVE */
#define NOTIFY 4 /* asynchronous notify */
#define SENDNB 5 /* nonblocking send */
+#define MINIX_KERNINFO 6 /* request kernel info structure */
#define SENDA 16 /* asynchronous send */
#define IPCNO_HIGHEST SENDA
char param_buf[MULTIBOOT_PARAM_BUF_SIZE];
/* Minix stuff */
- struct kmessages *kmess;
+ struct kmessages *kmessages;
int do_serial_debug; /* system serial output */
int serial_debug_baud; /* serial baud rate */
int minix_panicing; /* are we panicing? */
vir_bytes vir_addr, vir_bytes bytes, phys_bytes *phys_addr);
/* Shorthands for sys_getinfo() system call. */
-#define sys_getkmessages(dst) sys_getinfo(GET_KMESSAGES, dst, 0,0,0)
#define sys_getkinfo(dst) sys_getinfo(GET_KINFO, dst, 0,0,0)
#define sys_getloadinfo(dst) sys_getinfo(GET_LOADINFO, dst, 0,0,0)
#define sys_getmachine(dst) sys_getinfo(GET_MACHINE, dst, 0,0,0)
} bin[RANDOM_SOURCES];
};
+struct minix_kerninfo {
+ /* Binaries will depend on the offsets etc. in this
+ * structure, so it can't be changed willy-nilly. In
+ * other words, it is ABI-restricted.
+ */
+#define KERNINFO_MAGIC 0xfc3b84bf
+ u32_t kerninfo_magic;
+ u32_t minix_feature_flags;
+ u32_t flags_unused1;
+ u32_t flags_unused2;
+ u32_t flags_unused3;
+ u32_t flags_unused4;
+ struct kinfo *kinfo;
+ struct machine *machine;
+ struct kmessages *kmessages;
+ struct loadinfo *loadinfo;
+} __packed;
+
#endif /* _TYPE_H */
.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
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;
. += _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;
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,
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)
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) {
*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;
}
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
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;
/* 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; }
#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 */
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 */
}
/* 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);
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;
--- /dev/null
+#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 */
+
pop %ebp
ret
+ENTRY(_minix_kernel_info_struct)
+ push %ebp
+ movl %esp, %ebp
+ push %ebx
+ movl $0, %eax
+ movl $0, %ebx
+ movl $MINIX_KERNINFO, %ecx
+ int $IPCVEC /* trap to the kernel */
+ movl 8(%ebp), %ecx /* ecx = return struct ptr */
+ movl %ebx, (%ecx)
+ pop %ebx
+ pop %ebp
+ ret
+
ENTRY(_notify)
push %ebp
movl %esp, %ebp
vectorio.c shutdown.c sigaction.c sigpending.c sigreturn.c sigsuspend.c\
sigprocmask.c socket.c socketpair.c stat.c statvfs.c symlink.c \
sync.c syscall.c sysuname.c truncate.c umask.c unlink.c write.c \
- _exit.c _ucontext.c environ.c __getcwd.c vfork.c sizeup.c
+ _exit.c _ucontext.c environ.c __getcwd.c vfork.c sizeup.c init.c
# Minix specific syscalls.
SRCS+= cprofile.c lseek64.c sprofile.c _mcontext.c
--- /dev/null
+
+#include <stdio.h>
+#include <minix/ipc.h>
+
+struct minix_kerninfo *_minix_kerninfo = NULL;
+
+void __minix_init(void) __attribute__((__constructor__, __used__));
+
+void __minix_init(void)
+{
+ if((_minix_kernel_info_struct(&_minix_kerninfo)) != 0
+ || _minix_kerninfo->kerninfo_magic != KERNINFO_MAGIC) {
+ _minix_kerninfo = NULL;
+ }
+}
+
link.c _mcontext.c mknod.c mmap.c nanosleep.c open.c \
read.c sbrk.c select.c setuid.c sigprocmask.c stat.c \
stime.c syscall.c _ucontext.c umask.c unlink.c waitpid.c \
- brksize.S _ipc.S _senda.S ucontext.S mmap.c
+ brksize.S _ipc.S _senda.S ucontext.S mmap.c init.c
.PATH.c: ${LIBCSRCDIR}/sys-minix
.PATH.S: ${LIBCSRCDIR}/arch/${MACHINE}/sys-minix
SRCS+= ${i}
#include "inc.h"
#include <timers.h>
+#include <assert.h>
#include <machine/interrupt.h>
#include <minix/endpoint.h>
#include <minix/sysutil.h>
struct priv priv[NR_SYS_PROCS];
struct boot_image image[NR_BOOT_PROCS];
+extern struct minix_kerninfo *_minix_kerninfo;
+
/*===========================================================================*
* kmessages_dmp *
*===========================================================================*/
void kmessages_dmp()
{
- struct kmessages kmess; /* get copy of kernel messages */
+ struct kmessages *kmess; /* get copy of kernel messages */
char print_buf[_KMESS_BUF_SIZE+1]; /* this one is used to print */
int start; /* calculate start of messages */
int r;
+ int size;
- /* Try to get a copy of the kernel messages. */
- if ((r = sys_getkmessages(&kmess)) != OK) {
- printf("IS: warning: couldn't get copy of kmessages: %d\n", r);
- return;
- }
+ assert(_minix_kerninfo);
+ kmess = _minix_kerninfo->kmessages;
/* Try to print the kernel messages. First determine start and copy the
* buffer into a print-buffer. This is done because the messages in the
* copy may wrap (the kernel buffer is circular).
*/
- start = ((kmess.km_next + _KMESS_BUF_SIZE) - kmess.km_size) % _KMESS_BUF_SIZE;
+ start = ((kmess->km_next + _KMESS_BUF_SIZE) - kmess->km_size) % _KMESS_BUF_SIZE;
r = 0;
- while (kmess.km_size > 0) {
- print_buf[r] = kmess.km_buf[(start+r) % _KMESS_BUF_SIZE];
+ size = kmess->km_size;
+ while (size > 0) {
+ print_buf[r] = kmess->km_buf[(start+r) % _KMESS_BUF_SIZE];
r ++;
- kmess.km_size --;
+ size--;
}
print_buf[r] = 0; /* make sure it terminates */
printf("Dump of all messages generated by the kernel.\n\n");
kern_mappings[index].flags = flags;
kern_mappings[index].vir_addr = offset;
kern_mappings[index].flags =
- I386_VM_PRESENT | I386_VM_USER | I386_VM_WRITE;
+ I386_VM_PRESENT;
if(flags & VMMF_UNCACHED)
kern_mappings[index].flags |= PTF_NOCACHE;
+ if(flags & VMMF_USER)
+ kern_mappings[index].flags |= I386_VM_USER;
+ if(flags & VMMF_WRITE)
+ kern_mappings[index].flags |= I386_VM_WRITE;
+ if(flags & VMMF_GLO)
+ kern_mappings[index].flags |= I386_VM_GLOBAL;
if(addr % I386_PAGE_SIZE)
panic("VM: addr unaligned: %d", addr);
if(len % I386_PAGE_SIZE)
/* See if address is valid at all. */
if(!(region = map_lookup(vmp, addr))) {
- assert(PFERR_NOPAGE(err));
- printf("VM: pagefault: SIGSEGV %d bad addr 0x%x; %s\n",
+ if(PFERR_PROT(err)) {
+ printf("VM: pagefault: SIGSEGV %d protected addr 0x%x; %s\n",
ep, addr, pf_errstr(err));
+ } else {
+ assert(PFERR_NOPAGE(err));
+ printf("VM: pagefault: SIGSEGV %d bad addr 0x%x; %s\n",
+ ep, addr, pf_errstr(err));
+ }
if((s=sys_kill(vmp->vm_endpoint, SIGSEGV)) != OK)
panic("sys_kill failed: %d", s);
if((s=sys_vmctl(ep, VMCTL_CLEAR_PAGEFAULT, 0 /*unused*/)) != OK)