%assign i i+1
%endrep
+[extern Proc_int_SetIRQIP]
+
[global IrqCommon]
IrqCommon:
PUSH_GPR
push gs
push fs
-
+
+ mov rdi, [rsp+(16+2+2)*8] ; 2SReg + GPRs + Int/Errcode = RIP
+ call Proc_int_SetIRQIP
+ push rax
+
; mov rdi, csIRQ_Fired
; mov rsi, [rsp+(16+2)*8]
; call Log
- mov ebx, [rsp+(16+2)*8] ; Get interrupt number (16 GPRS + 2 SRs)
+ mov ebx, [rsp+(1+2+16)*8] ; Get interrupt number (16 GPRS + 2 SRs)
shl ebx, 2 ; *4
mov rax, gaIRQ_Handlers
lea rbx, [rax+rbx*8]
test rax, rax ; Check if it exists
jz .skip.%[i]
; Set RDI to IRQ number
- mov rdi, [rsp+(16+2+1)*8] ; Get IRQ number
+ mov rdi, [rsp+(16+2+1+1)*8] ; Get IRQ number
mov rsi, [rbx-gaIRQ_Handlers+gaIRQ_DataPtrs]
call rax ; Call
.skip.%[i]:
; ACK
mov al, 0x20
- mov rdi, [rsp+(16+2)*8] ; Get IRQ number
+ mov rdi, [rsp+(16+2+1)*8] ; Get IRQ number
cmp rdi, 8
jb .skipAckSecondary
out 0xA0, al
.skipAckSecondary:
out 0x20, al
+
+ pop rdi
+ call Proc_int_SetIRQIP
pop fs
pop gs
mov [rsp+0x28], r10 ; Arg4
mov [rsp+0x30], r8 ; Arg5
mov [rsp+0x38], r9 ; Arg6
-
+
+ mov rdi, rcx
+ call Proc_int_SetIRQIP
+
mov rdi, rsp
sub rsp, 8
call SyscallHandler
extern int MM_PageFault(tVAddr Addr, Uint ErrorCode, tRegs *Regs);
extern void Error_Backtrace(Uint IP, Uint BP);
extern void Proc_EnableSSE(void);
+extern void Threads_Dump(void);
extern void Proc_RestoreSSE(Uint32 Data);
// === PROTOTYPES ===
*(Uint8*)(Regs->RIP+2), *(Uint8*)(Regs->RIP+3)
);
break;
+ case 2: // NMI
+ Threads_Dump();
+ break;
}
__asm__ __volatile__ ("cli");
// === FUNCTIONS ===
void MM_FinishVirtualInit(void);
tVAddr MM_NewKStack(void);
-tVAddr MM_Clone(void);
+tVAddr MM_Clone(int bCopyUser);
tVAddr MM_NewWorkerStack(void *StackData, size_t StackSize);
#endif
Size += Addr & (PAGE_SIZE-1);
Addr &= ~(PAGE_SIZE-1);
- Addr &= ((1UL << 48)-1); // Clap to address space
+ // NC addr
+ if( ((Addr >> 47) & 1) != ((Addr>>48) == 0xFFFF))
+ return 0;
+ Addr &= ((1UL << 48)-1); // Clamp to address space
pml4 = Addr >> 39;
pdp = Addr >> 30;
dir = Addr >> 21;
tab = Addr >> 12;
- if( !(PAGEMAPLVL4(pml4) & 1) ) return 0;
- if( !(PAGEDIRPTR(pdp) & 1) ) return 0;
- if( !(PAGEDIR(dir) & 1) ) return 0;
- if( !(PAGETABLE(tab) & 1) ) return 0;
+ if( !(PAGEMAPLVL4(pml4) & 1) ) {
+ Log_Debug("MMVirt", "PML4E %i NP", pml4);
+ return 0;
+ }
+ if( !(PAGEDIRPTR(pdp) & 1) ) {
+ Log_Debug("MMVirt", "PDPE %i NP", pdp);
+ return 0;
+ }
+ if( !(PAGEDIR(dir) & 1) ) {
+ Log_Debug("MMVirt", "PDE %i NP", dir);
+ return 0;
+ }
+ if( !(PAGETABLE(tab) & 1) ) {
+ Log_Debug("MMVirt", "PTE %i NP", tab);
+ return 0;
+ }
bIsUser = !!(PAGETABLE(tab) & PF_USER);
while( Size >= PAGE_SIZE )
{
+ tab ++;
+ Size -= PAGE_SIZE;
+
if( (tab & 511) == 0 )
{
dir ++;
- if( ((dir >> 9) & 511) == 0 )
+ if( (dir & 511) == 0 )
{
pdp ++;
- if( ((pdp >> 18) & 511) == 0 )
+ if( (pdp & 511) == 0 )
{
pml4 ++;
- if( !(PAGEMAPLVL4(pml4) & 1) ) return 0;
+ if( !(PAGEMAPLVL4(pml4) & 1) ) {
+ Log_Debug("MMVirt", "IsValidBuffer - PML4E %x NP, Size=%x", pml4, Size);
+ return 0;
+ }
+ }
+ if( !(PAGEDIRPTR(pdp) & 1) ) {
+ Log_Debug("MMVirt", "IsValidBuffer - PDPE %x NP", pdp);
+ return 0;
}
- if( !(PAGEDIRPTR(pdp) & 1) ) return 0;
}
- if( !(PAGEDIR(dir) & 1) ) return 0;
+ if( !(PAGEDIR(dir) & 1) ) {
+ Log_Debug("MMVirt", "IsValidBuffer - PDE %x NP", dir);
+ return 0;
+ }
}
- if( !(PAGETABLE(tab) & 1) ) return 0;
- if( bIsUser && !(PAGETABLE(tab) & PF_USER) ) return 0;
-
- tab ++;
- Size -= PAGE_SIZE;
+ if( !(PAGETABLE(tab) & 1) ) {
+ Log_Debug("MMVirt", "IsValidBuffer - PTE %x NP", tab);
+ return 0;
+ }
+ if( bIsUser && !(PAGETABLE(tab) & PF_USER) ) {
+ Log_Debug("MMVirt", "IsValidBuffer - PTE %x Not user", tab);
+ return 0;
+ }
}
return 1;
}
// --- Address Space Clone --
-tPAddr MM_Clone(void)
+tPAddr MM_Clone(int bNoUserCopy)
{
tPAddr ret;
int i;
INVLPG_ALL();
// #3 Set Copy-On-Write to all user pages
- if( Threads_GetPID() != 0 )
+ if( Threads_GetPID() != 0 && !bNoUserCopy )
{
for( i = 0; i < 256; i ++)
{
PUSH_GPR
; Save RSP
mov [rdi], rsp
+ ; Call MM_Clone (with bNoUserCopy flag)
+ mov rdi, rdx
call MM_Clone
; Save CR3
mov rsi, [rsp+0x30] ; Saved version of RSI
extern Uint GetRIP(void); // start.asm
extern Uint SaveState(Uint *RSP, Uint *Regs);
-extern Uint Proc_CloneInt(Uint *RSP, Uint *CR3);
+extern Uint Proc_CloneInt(Uint *RSP, Uint *CR3, int bCopyUserVM);
extern void NewTaskHeader(void); // Actually takes cdecl args
extern void Proc_InitialiseSSE(void);
extern void Proc_SaveSSE(Uint DestPtr);
//void Proc_DumpThreadCPUState(tThread *Thread);
//void Proc_Reschedule(void);
void Proc_Scheduler(int CPU, Uint RSP, Uint RIP);
+Uint Proc_int_SetIRQIP(Uint RIP);
// === GLOBALS ===
//!\brief Used by desctab.asm in SyscallStub
if(!newThread) return -1;
// Save core machine state
- rip = Proc_CloneInt(&newThread->SavedState.RSP, &newThread->Process->MemState.CR3);
+ rip = Proc_CloneInt(&newThread->SavedState.RSP, &newThread->Process->MemState.CR3, !!(Flags & CLONE_NOUSER));
if(rip == 0) return 0; // Child
newThread->KernelStack = cur->KernelStack;
newThread->SavedState.RIP = rip;
void Proc_DumpThreadCPUState(tThread *Thread)
{
- Log(" At %04x:%016llx", Thread->SavedState.UserCS, Thread->SavedState.UserRIP);
+ if( Thread->CurCPU == GetCPUNum() ) {
+ // TODO: Backtrace to IRQ
+ Log(" IRQ %016llx", Thread->SavedState.UserRIP);
+ }
+ else {
+ Log(" At %016llx, SP=%016llx", Thread->SavedState.RIP, Thread->SavedState.RSP);
+ Log(" User %04x:%016llx", Thread->SavedState.UserCS, Thread->SavedState.UserRIP);
+ }
}
void Proc_Reschedule(void)
#endif
}
+Uint Proc_int_SetIRQIP(Uint RIP)
+{
+ int cpu = GetCPUNum();
+ tThread *thread = gaCPUs[cpu].Current;
+ Uint rv = thread->SavedState.UserRIP;
+ thread->SavedState.UserRIP = RIP;
+ return rv;
+}
+
// === EXPORTS ===
EXPORT(Proc_SpawnWorker);
if(c == 'p') {
Uint ptr = va_arg(args, Uint);
PUTCH('*'); PUTCH('0'); PUTCH('x');
- for( len = BITS/4; len --; )
+ for( len = BITS/4; len -- && ((ptr>>(len*4))&15) == 0; )
+ ;
+ for( len ++; len --; )
PUTCH( cUCDIGITS[ (ptr>>(len*4))&15 ] );
continue ;
}
}
-// NOTE: Strictly not libc, but lib.c is used by userland code too
+// NOTE: Strictly not libc, but lib.c is used by userland code too and hence these two
+// can't be in it.
/**
* \name Memory Validation
* \{
#include <events.h>
#define CHECK_NUM_NULLOK(v,size) \
- if((v)&&!Syscall_Valid((size),(v))){ret=-1;err=-EINVAL;break;}
+ if((v)&&!Syscall_Valid((size),(v))){LOG("CHECK_NUM_NULLOK: %p(%x) FAIL",v,size);ret=-1;err=-EINVAL;break;}
#define CHECK_STR_NULLOK(v) \
- if((v)&&!Syscall_ValidString((v))){ret=-1;err=-EINVAL;break;}
+ if((v)&&!Syscall_ValidString((v))){LOG("CHECK_STR_NULLOK: %p FAIL",v);ret=-1;err=-EINVAL;break;}
#define CHECK_NUM_NONULL(v,size) \
- if(!(v)||!Syscall_Valid((size),(v))){ret=-1;err=-EINVAL;break;}
+ if(!(v)||!Syscall_Valid((size),(v))){LOG("CHECK_NUM_NONULL: %p(%x) FAIL",v,size);ret=-1;err=-EINVAL;break;}
#define CHECK_STR_NONULL(v) \
- if(!(v)||!Syscall_ValidString((v))){ret=-1;err=-EINVAL;break;}
+ if(!(v)||!Syscall_ValidString((v))){LOG("CHECK_STR_NONULL: %p FAIL",v);ret=-1;err=-EINVAL;break;}
#define CHECK_STR_ARRAY(arr) do {\
int i;\
char **tmp = (char**)arr; \
*/
int Syscall_Valid(int Size, const void *Addr)
{
- if(!MM_IsUser( (tVAddr)Addr )) return 0;
+ if(!MM_IsUser( (tVAddr)Addr )) {
+ Log_Debug("Syscalls", "Syscall_Valid - %p not user", Addr);
+ return 0;
+ }
return CheckMem( Addr, Size );
}
default: break;
}
Log(" Priority %i, Quantum %i", thread->Priority, thread->Quantum);
- Log(" KStack 0x%x", thread->KernelStack);
+ Log(" KStack %p", thread->KernelStack);
if( thread->bInstrTrace )
Log(" Tracing Enabled");
Proc_DumpThreadCPUState(thread);
VBE_DISPI_INDEX_Y_OFFSET\r
};\r
\r
-extern void MM_DumpTables(tVAddr Start, tVAddr End);\r
-\r
// === PROTOTYPES ===\r
// Driver\r
int BGA_Install(char **Arguments);\r