/* Fixed system call vector. */
#define KERN_CALL_VECTOR 32 /* system calls are made with int SYSVEC */
#define IPC_VECTOR 33 /* interrupt vector for ipc */
-#define LEVEL0_VECTOR 34 /* for execution of a function at level 0 */
/* Suitable irq bases for hardware interrupts. Reprogram the 8259(s) from
* the PC BIOS defaults since the BIOS doesn't respect all the processor's
PRIVATE struct gate_table_s gate_table_common[] = {
{ ipc_entry, IPC_VECTOR, USER_PRIVILEGE },
{ kernel_call_entry, KERN_CALL_VECTOR, USER_PRIVILEGE },
- { level0_call, LEVEL0_VECTOR, TASK_PRIVILEGE },
{ NULL, 0, 0}
};
}
case VMCTL_FLUSHTLB:
{
- level0(reload_cr3);
+ reload_cr3();
return OK;
}
}
data_copy(caller->p_endpoint, (vir_bytes) m_ptr->INT86_REG86,
KERNEL, (vir_bytes) ®86, sizeof(reg86));
- level0(int86);
+ int86();
/* Copy results back to the caller */
data_copy(KERNEL, (vir_bytes) ®86,
struct priv *privp;
struct io_range *iorp;
struct proc *destproc;
+ int retval;
/* Allow safe copies and accesses to SELF */
if ((m_ptr->DIO_REQUEST & _DIO_SAFEMASK) != _DIO_SAFE &&
}
/* current process must be target for phys_* to be OK */
- vm_set_cr3(destproc);
+ switch_address_space(destproc);
switch (req_type)
{
kprintf(
"do_sdevio: I/O port check failed for proc %d, port 0x%x\n",
m_ptr->m_source, port);
- return EPERM;
+ retval = EPERM;
+ goto return_error;
}
}
if (port & (size-1))
{
kprintf("do_devio: unaligned port 0x%x (size %d)\n", port, size);
- return EPERM;
+ retval = EPERM;
+ goto return_error;
}
/* Perform device I/O for bytes and words. Longs are not supported. */
switch (req_type) {
case _DIO_BYTE: phys_insb(port, phys_buf, count); break;
case _DIO_WORD: phys_insw(port, phys_buf, count); break;
- default: return(EINVAL);
+ default:
+ retval = EINVAL;
+ goto return_error;
}
} else if (req_dir == _DIO_OUTPUT) {
switch (req_type) {
case _DIO_BYTE: phys_outsb(port, phys_buf, count); break;
case _DIO_WORD: phys_outsw(port, phys_buf, count); break;
- default: return(EINVAL);
+ default:
+ retval = EINVAL;
+ goto return_error;
}
}
else {
- return(EINVAL);
+ retval = EINVAL;
+ goto return_error;
}
- return(OK);
+ retval = OK;
+
+return_error:
+ /* switch back to the address of the process which made the call */
+ switch_address_space(caller);
+ return retval;
}
#endif /* USE_SDEVIO */
#define SS_INDEX 5 /* kernel SS (386: monitor SS at startup) */
#define CS_INDEX 6 /* kernel CS */
#define MON_CS_INDEX 7 /* temp for BIOS (386: monitor CS at startup) */
-#define DS_286_INDEX 8 /* scratch 16-bit source segment */
-#define ES_286_INDEX 9 /* scratch 16-bit destination segment */
-#define TSS_INDEX 10 /* kernel TSS */
-#define FIRST_LDT_INDEX 11 /* rest of descriptors are LDT's */
+#define TSS_INDEX 8 /* kernel TSS */
+#define FIRST_LDT_INDEX 9 /* rest of descriptors are LDT's */
/* Descriptor structure offsets. */
#define DESC_BASE 2 /* to base_low */
#define DS_SELECTOR DS_INDEX * DESC_SIZE
#define ES_SELECTOR ES_INDEX * DESC_SIZE
/* flat DS is less privileged ES */
-#define FLAT_DS_SELECTOR ES_SELECTOR | TASK_PRIVILEGE
+#define FLAT_DS_SELECTOR ES_SELECTOR
#define SS_SELECTOR SS_INDEX * DESC_SIZE
#define CS_SELECTOR CS_INDEX * DESC_SIZE
#define MON_CS_SELECTOR MON_CS_INDEX * DESC_SIZE
#define TSS_SELECTOR TSS_INDEX * DESC_SIZE
-#define DS_286_SELECTOR DS_286_INDEX*DESC_SIZE | TASK_PRIVILEGE
-#define ES_286_SELECTOR ES_286_INDEX*DESC_SIZE | TASK_PRIVILEGE
/* Privileges. */
#define INTR_PRIVILEGE 0 /* kernel and interrupt handlers */
-#define TASK_PRIVILEGE 1 /* kernel tasks */
#define USER_PRIVILEGE 3 /* servers and user processes */
#define RPL_MASK 0x03 /* bits in selector RPL */
.globl mem_rdw /* copy one word from [segment:offset] */
.globl reset /* reset the system */
.globl halt_cpu/* halts the current cpu when idle */
-.globl level0 /* call a function at level 0 */
.globl read_cpu_flags /* read the cpu flags */
.globl read_cr0 /* read cr0 */
.globl read_cr2 /* read cr2 */
.globl getcr3val
.globl write_cr0 /* write a value in cr0 */
+.globl read_cr3
.globl read_cr4
-.globl thecr3
.globl write_cr4
.globl catch_pagefaults
cli
ret
-/*===========================================================================*/
-/* level0 */
-/*===========================================================================*/
-/*
- * PUBLIC void level0(void (*func)(void))
- * Call a function at permission level 0. This allows kernel tasks to do
- * things that are only possible at the most privileged CPU level.
- */
-level0:
- /* check whether we are already running in kernel, the kernel cs
- * selector has 3 lower bits zeroed */
- mov %cs, %ax
- cmpw $CS_SELECTOR, %ax
- jne 0f
-
- /* call the function directly as if it was a normal function call */
- mov 4(%esp), %eax
- call *%eax
- ret
-
-
- /* if not runnig in the kernel yet, trap to kernel */
-0:
- mov 4(%esp), %eax
- int $LEVEL0_VECTOR
- ret
-
/*===========================================================================*/
/* read_flags */
/*===========================================================================*/
mov %cr2, %eax
ret
+/*===========================================================================*/
+/* read_cr3 */
+/*===========================================================================*/
+/* PUBLIC unsigned long read_cr3(void); */
+read_cr3:
+ push %ebp
+ mov %esp, %ebp
+
+ /* DO NOT CHANGE THE OPERAND!!! gas2ack does not handle it yet */
+ mov %cr3, %eax
+ pop %ebp
+ ret
+
/*===========================================================================*/
/* read_cr4 */
/*===========================================================================*/
/* PUBLIC unsigned long getcr3val(void); */
getcr3val:
mov %cr3, %eax
- mov %eax, thecr3
ret
/*
{
if(vm_running)
minix_panic("vm_init: vm_running", NO_NUM);
- vm_set_cr3(newptproc);
- level0(vm_enable_paging);
+ switch_address_space(newptproc);
+ vm_enable_paging();
vm_running = 1;
}
PTR = I386_BIG_PAGE_SIZE*PDE + offset; \
REMAIN = MIN(REMAIN, I386_BIG_PAGE_SIZE - offset); \
if(1 || mustinvl) { \
- level0(reload_cr3); \
+ reload_cr3(); \
} \
} \
}
vmassert(ptproc);
vmassert(proc_ptr);
- vmassert(read_cr3() == ptproc->p_seg.p_cr3);
+ vmassert(getcr3val() == ptproc->p_seg.p_cr3);
procslot = ptproc->p_nr;
return v;
}
-PRIVATE u32_t vm_cr3; /* temp arg to level0() func */
-
-PRIVATE void set_cr3()
-{
- write_cr3(vm_cr3);
-}
-
-PUBLIC void vm_set_cr3(struct proc *newptproc)
-{
- int u = 0;
- if(!intr_disabled()) { lock; u = 1; }
- vm_cr3= newptproc->p_seg.p_cr3;
- if(vm_cr3) {
- level0(set_cr3);
- ptproc = newptproc;
- }
- if(u) { unlock; }
-}
-
PRIVATE char *cr0_str(u32_t e)
{
static char str[80];
#endif
- vm_set_cr3(rp);
-
PHYS_COPY_CATCH(vir2phys(&rp->p_delivermsg),
rp->p_delivermsg_lin, sizeof(message), addr);
return;
}
-u32_t thecr3;
-
-u32_t read_cr3(void)
-{
- level0(getcr3val);
- return thecr3;
-}
-
-
/*===========================================================================*
* lin_memset *
*===========================================================================*/
* lapic address. Bad things would happen. It is unfortunate but such is
* life
*/
- level0(i386_watchdog_start);
+ i386_watchdog_start();
#endif
return OK;
.globl restart
.globl reload_cr3
-.globl write_cr3
.globl divide_error
.globl single_step_exception
.globl hwint14
.globl hwint15
-.globl level0_call
-
/* Exported variables. */
.globl begbss
.globl begdata
pop %ebp
ret
-/*===========================================================================*/
-/* write_cr3 */
-/*===========================================================================*/
-/* PUBLIC void write_cr3(unsigned long value); */
-write_cr3:
- push %ebp
- mov %esp, %ebp
- mov 8(%ebp), %eax
- mov %cr3, %ecx
- cmp %ecx, %eax
- jz 0f
- mov %eax, %cr3
- movl $0, dirtypde
-0:
- pop %ebp
- ret
-
-/*===========================================================================*/
-/* level0_call */
-/*===========================================================================*/
-level0_call:
-/*
- * which level0 function to call was passed here by putting it in %eax
- */
- SAVE_PROCESS_CTX(0)
- /* for stack trace */
- movl $0, %ebp
- /*
- * the function to call is in %eax, set in userspace. SAVE_PROCESS_CTX()
- * does not clobber this register so we can use it straightaway
- */
- call *%eax
- jmp restart
-
-
/*===========================================================================*/
/* reload_cr3 */
/*===========================================================================*/
kinfo.code_base, kinfo.code_size, INTR_PRIVILEGE);
init_dataseg(&gdt[DS_INDEX],
kinfo.data_base, kinfo.data_size, INTR_PRIVILEGE);
- init_dataseg(&gdt[ES_INDEX], 0L, 0, TASK_PRIVILEGE);
-
- /* Build scratch descriptors for functions in klib88. */
- init_dataseg(&gdt[DS_286_INDEX], 0L, 0, TASK_PRIVILEGE);
- init_dataseg(&gdt[ES_286_INDEX], 0L, 0, TASK_PRIVILEGE);
+ init_dataseg(&gdt[ES_INDEX], 0L, 0, INTR_PRIVILEGE);
/* Build local descriptors in GDT for LDT's in process table.
* The LDT's are allocated at compile time in the process table, and
{ simd_exception, SIMD_EXCEPTION_VECTOR, INTR_PRIVILEGE },
{ ipc_entry, IPC_VECTOR, USER_PRIVILEGE },
{ kernel_call_entry, KERN_CALL_VECTOR, USER_PRIVILEGE },
- { level0_call, LEVEL0_VECTOR, TASK_PRIVILEGE },
{ NULL, 0, 0}
};
{
/* This is called at system initialization from main() and by do_newmap().
* The code has a separate function because of all hardware-dependencies.
- * Note that IDLE is part of the kernel and gets TASK_PRIVILEGE here.
*/
phys_bytes code_bytes;
phys_bytes data_bytes;
code_bytes = data_bytes; /* common I&D, poor protect */
else
code_bytes = (phys_bytes) rp->p_memmap[T].mem_len << CLICK_SHIFT;
- if( (iskernelp(rp)))
- privilege = TASK_PRIVILEGE;
- else
- privilege = USER_PRIVILEGE;
+ privilege = USER_PRIVILEGE;
init_codeseg(&rp->p_seg.p_ldt[CS_LDT_INDEX],
(phys_bytes) rp->p_memmap[T].mem_phys << CLICK_SHIFT,
code_bytes, privilege);
if (isemptyp(rp))
continue;
- if( (iskernelp(rp)))
- privilege = TASK_PRIVILEGE;
- else
privilege = USER_PRIVILEGE;
cs = (CS_LDT_INDEX*DESC_SIZE) | TI | privilege;
/* memory.c */
_PROTOTYPE( void i386_freepde, (int pde));
_PROTOTYPE( void getcr3val, (void));
-_PROTOTYPE( void vm_set_cr3, (struct proc *));
/* exception.c */
_PROTOTYPE( void exception, (struct exception_frame * frame));
/* klib386.s */
-_PROTOTYPE( void level0, (void (*func)(void)) );
_PROTOTYPE( void monitor, (void) );
_PROTOTYPE( void reset, (void) );
_PROTOTYPE( void int86, (void) );
_PROTOTYPE( reg_t read_cr0, (void) );
_PROTOTYPE( reg_t read_cr2, (void) );
_PROTOTYPE( void write_cr0, (unsigned long value) );
+_PROTOTYPE( unsigned long read_cr3, (void) );
_PROTOTYPE( unsigned long read_cr4, (void) );
_PROTOTYPE( void write_cr4, (unsigned long value) );
-_PROTOTYPE( void write_cr3, (unsigned long value) );
_PROTOTYPE( unsigned long read_cpu_flags, (void) );
_PROTOTYPE( void phys_insb, (U16_t port, phys_bytes buf, size_t count) );
_PROTOTYPE( void phys_insw, (U16_t port, phys_bytes buf, size_t count) );
PUBLIC void arch_monitor(void)
{
- level0(monitor);
+ monitor();
}
PUBLIC int cpu_has_tsc;
u16_t magic = STOP_MEM_CHECK;
phys_copy(vir2phys(&magic), SOFT_RESET_FLAG_ADDR,
SOFT_RESET_FLAG_SIZE);
- level0(reset);
+ reset();
}
}