From 8051546ad5894e093211d2ec69dde6b99cdaa71d Mon Sep 17 00:00:00 2001 From: John Hodge Date: Fri, 19 Nov 2010 23:48:01 +0800 Subject: [PATCH] Multiple IPStack Related changes (and other bugfixes) - Added route determining to arp.c - Changed route source API to take an interface pointer - Fixed loopback device behavior ('LOOPBACK' is a special adapter path) - Required fixing the fifo driver > Size on /Defices/fifo directory should be 1, not 0 > Set default fifo to be blocking - Slight change to ifconfig to ignore iterfaces that return a -1 type, or do not conform to the spec. - Fixed triple fault when a kernel thread is spawned before init is started (caused by a kernel stack being marked as COW, causing an uncatched double fault) --- Kernel/arch/x86/mm_virt.c | 57 ++++++++++++----------- Kernel/arch/x86/proc.asm | 9 ++-- Kernel/arch/x86/proc.c | 3 +- Kernel/drv/fifo.c | 10 +++- Modules/IPStack/arp.c | 16 ++++++- Modules/IPStack/interface.c | 36 ++++++++++++++ Modules/IPStack/ipstack.h | 2 + Modules/IPStack/main.c | 7 ++- Modules/IPStack/routing.c | 12 +++-- Usermode/Applications/ifconfig_src/main.c | 7 ++- 10 files changed, 119 insertions(+), 40 deletions(-) diff --git a/Kernel/arch/x86/mm_virt.c b/Kernel/arch/x86/mm_virt.c index 3c893f8e..2b2f02c1 100644 --- a/Kernel/arch/x86/mm_virt.c +++ b/Kernel/arch/x86/mm_virt.c @@ -541,37 +541,40 @@ tPAddr MM_Clone(void) //LOG("Allocated Directory (%x)", *gpTmpCR3); memsetd( gaTmpDir, 0, 1024 ); - // Copy Tables - for( i = 0; i < 768; i ++) - { - // Check if table is allocated - if( !(gaPageDir[i] & PF_PRESENT) ) { - gaTmpDir[i] = 0; - page += 1024; - continue; - } - - // Allocate new table - gaTmpDir[i] = MM_AllocPhys() | (gaPageDir[i] & 7); - INVLPG( &gaTmpTable[page] ); - // Fill - for( j = 0; j < 1024; j ++, page++ ) + if( Threads_GetPID() != 0 ) + { + // Copy Tables + for( i = 0; i < 768; i ++) { - if( !(gaPageTable[page] & PF_PRESENT) ) { - gaTmpTable[page] = 0; + // Check if table is allocated + if( !(gaPageDir[i] & PF_PRESENT) ) { + gaTmpDir[i] = 0; + page += 1024; continue; } - // Refrence old page - MM_RefPhys( gaPageTable[page] & ~0xFFF ); - // Add to new table - if(gaPageTable[page] & PF_WRITE) { - gaTmpTable[page] = (gaPageTable[page] & ~PF_WRITE) | PF_COW; - gaPageTable[page] = (gaPageTable[page] & ~PF_WRITE) | PF_COW; - INVLPG( page << 12 ); + // Allocate new table + gaTmpDir[i] = MM_AllocPhys() | (gaPageDir[i] & 7); + INVLPG( &gaTmpTable[page] ); + // Fill + for( j = 0; j < 1024; j ++, page++ ) + { + if( !(gaPageTable[page] & PF_PRESENT) ) { + gaTmpTable[page] = 0; + continue; + } + + // Refrence old page + MM_RefPhys( gaPageTable[page] & ~0xFFF ); + // Add to new table + if(gaPageTable[page] & PF_WRITE) { + gaTmpTable[page] = (gaPageTable[page] & ~PF_WRITE) | PF_COW; + gaPageTable[page] = (gaPageTable[page] & ~PF_WRITE) | PF_COW; + INVLPG( page << 12 ); + } + else + gaTmpTable[page] = gaPageTable[page]; } - else - gaTmpTable[page] = gaPageTable[page]; } } @@ -685,6 +688,7 @@ tVAddr MM_NewWorkerStack() __asm__ __volatile__ ("mov %%esp, %0": "=r"(esp)); __asm__ __volatile__ ("mov %%ebp, %0": "=r"(ebp)); + // TODO: Thread safety // Find a free worker stack address for(base = giLastUsedWorker; base < NUM_WORKER_STACKS; base++) { @@ -732,6 +736,7 @@ tVAddr MM_NewWorkerStack() // Mapping Time! for( addr = 0; addr < WORKER_STACK_SIZE; addr += 0x1000 ) + //for( addr = WORKER_STACK_SIZE; addr; addr -= 0x1000 ) { pages[ addr >> 12 ] = MM_AllocPhys(); gaTmpTable[ (base + addr) >> 12 ] = pages[addr>>12] | 3; diff --git a/Kernel/arch/x86/proc.asm b/Kernel/arch/x86/proc.asm index 732d35fc..fd372dbf 100644 --- a/Kernel/arch/x86/proc.asm +++ b/Kernel/arch/x86/proc.asm @@ -238,10 +238,11 @@ Proc_ReturnToUser: [global GetCPUNum] GetCPUNum: ; TODO: Store in debug registers - xor eax, eax - str ax - sub ax, 0x30 - shr ax, 3 ; ax /= 8 +; xor eax, eax +; str ax +; sub ax, 0x30 +; shr ax, 3 ; ax /= 8 + mov eax, dr1 ret ; Usermode code exported by the kernel diff --git a/Kernel/arch/x86/proc.c b/Kernel/arch/x86/proc.c index 5e9d1bbc..ad83c991 100644 --- a/Kernel/arch/x86/proc.c +++ b/Kernel/arch/x86/proc.c @@ -14,6 +14,7 @@ // === FLAGS === #define DEBUG_TRACE_SWITCH 0 +#define DEBUG_DISABLE_DOUBLEFAULT 1 // === CONSTANTS === #define SWITCH_MAGIC 0xFF5317C8 // FF SWITCH - There is no code in this area @@ -286,7 +287,7 @@ void ArchThreads_Init(void) MM_FinishVirtualInit(); #endif - #if 0 + #if !DEBUG_DISABLE_DOUBLEFAULT // Initialise Double Fault TSS gGDT[5].BaseLow = (Uint)&gDoubleFault_TSS & 0xFFFF; gGDT[5].BaseMid = (Uint)&gDoubleFault_TSS >> 16; diff --git a/Kernel/drv/fifo.c b/Kernel/drv/fifo.c index 83d11755..cbbd1074 100644 --- a/Kernel/drv/fifo.c +++ b/Kernel/drv/fifo.c @@ -38,6 +38,7 @@ MODULE_DEFINE(0, 0x0032, FIFO, FIFO_Install, NULL, NULL); tDevFS_Driver gFIFO_DriverInfo = { NULL, "fifo", { + .Size = 1, .NumACLs = 1, .ACLs = &gVFS_ACL_EveryoneRW, .Flags = VFS_FFLAG_DIRECTORY, @@ -80,6 +81,7 @@ int FIFO_IOCtl(tVFS_Node *Node, int Id, void *Data) char *FIFO_ReadDir(tVFS_Node *Node, int Id) { tPipe *tmp = gFIFO_NamedPipes; + // Entry 0 is Anon Pipes if(Id == 0) return strdup("anon"); @@ -216,9 +218,12 @@ Uint64 FIFO_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer) while(remaining) { // Wait for buffer to fill - if(pipe->Flags & PF_BLOCKING) - while(pipe->ReadPos == pipe->WritePos) + if(pipe->Flags & PF_BLOCKING) { + while(pipe->ReadPos == pipe->WritePos) { Threads_Yield(); + //MAGIC_BREAK(); + } + } else if(pipe->ReadPos == pipe->WritePos) return 0; @@ -325,6 +330,7 @@ tPipe *FIFO_Int_NewPipe(int Size, char *Name) memset(ret, 0, allocsize); ret->Name = Name; + ret->Flags = PF_BLOCKING; // Allocate Buffer ret->BufSize = Size; diff --git a/Modules/IPStack/arp.c b/Modules/IPStack/arp.c index fda1b2f9..9e92414b 100644 --- a/Modules/IPStack/arp.c +++ b/Modules/IPStack/arp.c @@ -1,13 +1,14 @@ /* * Acess2 IP Stack * - Address Resolution Protocol + * - Part of the IPv4 protocol */ #define DEBUG 0 #include "ipstack.h" #include "arp.h" #include "link.h" -#define ARPv6 1 +#define ARPv6 0 #define ARP_CACHE_SIZE 64 #define ARP_MAX_AGE (60*60*1000) // 1Hr @@ -76,8 +77,19 @@ tMacAddr ARP_Resolve4(tInterface *Interface, tIPv4 Address) ENTER("pInterface xAddress", Interface, Address); // Check routing tables - // Replace address with gateway if needed + { + tRoute *route = IPStack_FindRoute(4, Interface, &Address); + if( route ) { + // If the next hop is defined, use it + // - 0.0.0.0 as the next hop means "no next hop / direct" + if( ((tIPv4*)route->NextHop)->L != 0 ) { + // Recursion: see /Recursion/ + return ARP_Resolve4(Interface, *(tIPv4*)route->NextHop); + } + } + } + // Check ARP Cache Mutex_Acquire( &glARP_Cache4 ); for( i = 0; i < giARP_Cache4Space; i++ ) { diff --git a/Modules/IPStack/interface.c b/Modules/IPStack/interface.c index 445e5892..c6f55ba9 100644 --- a/Modules/IPStack/interface.c +++ b/Modules/IPStack/interface.c @@ -52,6 +52,11 @@ tInterface *gIP_Interfaces = NULL; tInterface *gIP_Interfaces_Last = NULL; tSocketFile *gIP_FileTemplates; + +tAdapter gIP_LoopAdapter = { + DeviceLen: 8, + Device: "LOOPBACK" + }; tMutex glIP_Adapters; tAdapter *gIP_Adapters = NULL; int giIP_NextIfaceId = 1; @@ -531,6 +536,37 @@ tAdapter *IPStack_GetAdapter(const char *Path) ENTER("sPath", Path); + // Check for loopback + if( strcmp(Path, "LOOPBACK") == 0 ) + { + // Initialise if required + if( gIP_LoopAdapter.DeviceFD == 0 ) + { + dev = &gIP_LoopAdapter; + + dev->NRef = 1; + dev->DeviceLen = 8; + + dev->DeviceFD = VFS_Open( "/Devices/fifo/anon", VFS_OPENFLAG_READ|VFS_OPENFLAG_WRITE ); + if( dev->DeviceFD == -1 ) { + Log_Warning("IPStack", "Unable to open FIFO '/Devices/fifo/anon' for loopback"); + return NULL; + } + + dev->MacAddr.B[0] = 'A'; + dev->MacAddr.B[1] = 'c'; + dev->MacAddr.B[2] = 'e'; + dev->MacAddr.B[3] = 's'; + dev->MacAddr.B[4] = 's'; + dev->MacAddr.B[5] = '2'; + + // Start watcher + Link_WatchDevice( dev ); + } + LEAVE('p', &gIP_LoopAdapter); + return &gIP_LoopAdapter; + } + Mutex_Acquire( &glIP_Adapters ); // Check if this adapter is already open diff --git a/Modules/IPStack/ipstack.h b/Modules/IPStack/ipstack.h index db93328d..071c62b1 100644 --- a/Modules/IPStack/ipstack.h +++ b/Modules/IPStack/ipstack.h @@ -116,4 +116,6 @@ extern int IPStack_AddFile(tSocketFile *File); extern int IPStack_GetAddressSize(int AddressType); extern int IPStack_CompareAddress(int AddressType, void *Address1, void *Address2, int CheckBits); +extern tRoute *IPStack_FindRoute(int AddressType, tInterface *Interface, void *Address); + #endif diff --git a/Modules/IPStack/main.c b/Modules/IPStack/main.c index 585f8c3e..bec82b33 100644 --- a/Modules/IPStack/main.c +++ b/Modules/IPStack/main.c @@ -71,10 +71,15 @@ int IPStack_Install(char **Arguments) // - is a condensed hexadecimal stream (in big endian) // (E.g. 0A000201 for 10.0.2.1 IPv4) // - is the number of subnet bits (E.g. 24 for an IPv4 Class C) + // Example: /Devices/ne2k/0,4,0A00020A,24 + + // I could also define routes using ,,, + // Example: 1,00000000,0,0A000201 } } - gIP_LoopInterface.Adapter = IPStack_GetAdapter("/Devices/fifo/anon"); + // Initialise loopback interface + gIP_LoopInterface.Adapter = IPStack_GetAdapter("LOOPBACK"); DevFS_AddDevice( &gIP_DriverInfo ); diff --git a/Modules/IPStack/routing.c b/Modules/IPStack/routing.c index 51eb6db5..381ddf7a 100644 --- a/Modules/IPStack/routing.c +++ b/Modules/IPStack/routing.c @@ -18,7 +18,7 @@ char *IPStack_RouteDir_ReadDir(tVFS_Node *Node, int Pos); tVFS_Node *IPStack_RouteDir_FindDir(tVFS_Node *Node, const char *Name); int IPStack_RouteDir_IOCtl(tVFS_Node *Node, int ID, void *Data); int IPStack_Route_Create(const char *InterfaceName); -tRoute *IPStack_FindRoute(int AddressType, void *Address); +tRoute *IPStack_FindRoute(int AddressType, tInterface *Interface, void *Address); // - Individual Routes int IPStack_Route_IOCtl(tVFS_Node *Node, int ID, void *Data); @@ -132,7 +132,7 @@ int IPStack_RouteDir_IOCtl(tVFS_Node *Node, int ID, void *Data) if( !CheckMem(Data, sizeof(int) + IPStack_GetAddressSize(data->Type)) ) return -1; - rt = IPStack_FindRoute(data->Type, data->Addr); + rt = IPStack_FindRoute(data->Type, NULL, data->Addr); if( !rt ) return 0; @@ -200,15 +200,21 @@ int IPStack_Route_Create(const char *InterfaceName) /** */ -tRoute *IPStack_FindRoute(int AddressType, void *Address) +tRoute *IPStack_FindRoute(int AddressType, tInterface *Interface, void *Address) { tRoute *rt; tRoute *best = NULL; + if( Interface && AddressType != Interface->Type ) return NULL; + for( rt = gIP_Routes; rt; rt = rt->Next ) { + // Check interface + if( Interface && rt->Interface != Interface ) continue; + // Check address type if( rt->AddressType != AddressType ) continue; + // Check if the address matches if( !IPStack_CompareAddress(AddressType, rt->Network, Address, rt->SubnetBits) ) continue; diff --git a/Usermode/Applications/ifconfig_src/main.c b/Usermode/Applications/ifconfig_src/main.c index 3f7cfc47..b80f6fa7 100644 --- a/Usermode/Applications/ifconfig_src/main.c +++ b/Usermode/Applications/ifconfig_src/main.c @@ -134,6 +134,11 @@ void DumpInterface(const char *Name) type = ioctl(fd, 4, NULL); + // Ignore -1 values + if( type == -1 ) { + return ; + } + printf("%s:\t", Name); { int call_num = ioctl(fd, 3, "get_device"); @@ -213,7 +218,7 @@ void AddRoute(const char *Interface, void *Dest, int MaskBits, void *NextHop) // Create route fd = open(IPSTACK_ROOT"/routes", 0); - num = ioctl(fd, ioctl(fd, 3, "add_route"), Interface); + num = ioctl(fd, ioctl(fd, 3, "add_route"), (char*)Interface); close(fd); // Open route -- 2.20.1