private uint ActiveIsrInterrupt() { uint isr = ~0u; uint i; for (i = 0; i < 0x80; i += 0x10) { uint value = Read(ApicOffset.IsrBase + i); if (value != 0) { lastByteValue = (int)value; lastByte = i; DebugStub.Assert((value & (value - 1)) == 0); isr = i * 2 + Log2(value); lastIsr = isr; break; } } i += 0x10; for (; i < 0x80; i += 0x10) { uint value = Read(ApicOffset.IsrBase + i); DebugStub.Assert(value == 0); } DebugStub.Assert(isr != ~0u); return(isr); }
public override void AckIrq(byte irq) { DebugStub.Assert(Processor.InterruptsDisabled()); #if PIC_DEBUG DumpRegisters(); #endif // Mark the IRQ as activated and mask it #if DEBUG_INTERRUPTS DebugStub.Print("Int{0:x2} Acked, Mask={1:x4}\n", __arglist(irq + baseVector, irqMask)); #endif // Quite the interrupt controller. IoResult result; if (irq >= 8) { result = pic1CtrlPort.Write8NoThrow(PIC_NS_EOI); DebugStub.Assert(IoResult.Success == result); } result = pic0CtrlPort.Write8NoThrow(PIC_NS_EOI); DebugStub.Assert(IoResult.Success == result); #if PIC_DEBUG DumpRegisters(); #endif }
internal void PitWrite(int pt) { #if TIMER_NO_GO return; #endif // TIMER_NO_GO IoResult result; result = CWPort.Write8NoThrow(i8254_CW_MODE0 | i8254_CW_BOTH | i8254_CW_SEL0); DebugStub.Assert(IoResult.Success == result); result = C0Port.Write8NoThrow((byte)(pt & 0xff)); DebugStub.Assert(IoResult.Success == result); result = C0Port.Write8NoThrow((byte)(pt >> 8)); DebugStub.Assert(IoResult.Success == result); byte v; do { result = CWPort.Write8NoThrow(i8254_RB_NOCOUNT | i8254_RB_SEL0); DebugStub.Assert(IoResult.Success == result); result = C0Port.Read8NoThrow(out v); DebugStub.Assert(IoResult.Success == result); } while ((v & i8254_RB_NULL) == i8254_RB_NULL); }
///////////////////////////////////// // PUBLIC METHODS ///////////////////////////////////// public unsafe PhysicalHeap(UIntPtr start, UIntPtr limit) { DebugStub.Assert(MemoryManager.IsPageAligned(start)); DebugStub.Assert(MemoryManager.IsPageAligned(limit)); // Note that this wastes a little bit of memory by allocating // table space to describe page-table memory! UIntPtr numPages = MemoryManager.PagesFromBytes(limit - start); UIntPtr bytesForTable = numPages * BytesPerTableEntry; bytesForTable = MemoryManager.PagePad(bytesForTable); UIntPtr pagesForTable = MemoryManager.PagesFromBytes(bytesForTable); pageCount = numPages - pagesForTable; startAddr = start + bytesForTable; heapLimit = limit; pageTable = (ushort *)start; heapLock = new SpinLock(SpinLock.Types.PhysicalHeap); // The entire heap is free to start out with freeList = new FreeList(); // Initialize the page table SetPages(startAddr, pageCount, FreePage); fixed(PhysicalHeap *thisPtr = &this) { freeList.CreateAndInsert(thisPtr, startAddr, pageCount); } CheckConsistency(); }
public Bytes PopAllPackets() { Bytes packet; int sizeOfData; Bytes buffer; if (byteCount <= 0) { DebugStub.WriteLine("UDP PopAllPackets: no data???\n"); DebugStub.Break(); return(null); } using (thisLock.Lock()) { DebugPrint("Popping {0} bytes of data to client\n", byteCount); buffer = new Bytes(new byte[byteCount]); VectorQueueByte incomingPacketQueue = packetContainer.Acquire(); int offset = 0; while ((packet = incomingPacketQueue.ExtractHead()) != null) { VTable.Assert(packet != null); Bitter.Copy(buffer, offset, packet.Length, packet, 0); offset += packet.Length; byteCount -= packet.Length; //delete packet; } packetContainer.Release(incomingPacketQueue); DebugStub.Assert(byteCount == 0); } return(buffer); }
/// <summary> /// Generic copy (either from kernel or to kernel) /// Determines if the thing we are moving is an endpoint and copies it accordingly. /// </summary> public static Allocation *MoveData(SharedHeap fromHeap, SharedHeap toHeap, Process newOwner, Allocation *data) { if (data == null) { return(data); } if (!fromHeap.Validate(data)) { throw new ArgumentException("Bad argument. Not visible"); } // We can only transfer either into our out of the kernel's heap DebugStub.Assert(fromHeap == SharedHeap.KernelSharedHeap || toHeap == SharedHeap.KernelSharedHeap); if (SystemType.IsSubtype(data, EndpointCoreSystemType)) { // we have an endpoint DeliveryImpl di = EndpointCore.AllocationEndpointDeliveryImpl(data); return(di.MoveEndpoint(fromHeap, toHeap, newOwner)); } else { // we have a NON-endpoint // TODO FIX this! return(null); // MoveNonEndpoint(fromHeap, toHeap, newOwner, data); } }
private unsafe ushort PageWord(UIntPtr pageIdx) { DebugStub.Assert(pageIdx < pageCount, "PhysicalHeap.PageWord pageIdx {0} >= pageCount {1}", __arglist(pageIdx, pageCount)); return(*(pageTable + (ulong)pageIdx)); }
private unsafe void CheckConsistency() { #if SELF_TEST // Top bits should be kept clear DebugStub.Assert((blockMap & UnusedMask) == 0); fixed(uint *pBeforeRegions = &blockMap) { uint *pRegion = pBeforeRegions; pRegion++; for (uint i = 0; i < RegionsPerBlock; i++, pRegion++) { if ((*pRegion) != FullRegion) { DebugStub.Assert((blockMap & ((uint)1 << (int)i)) == 0, "PhysicalPages.PageBlock.CheckConsistency: blockMap shows a free region as full"); } else { DebugStub.Assert((blockMap & ((uint)1 << (int)i)) != 0, "PhysicalPages.PageBlock.CheckConsistency: blockMap shows a full region as free"); } } } #endif }
// Allocate a single hardware page internal unsafe static PhysicalAddress AllocPage() { bool iflag = Lock(); try { CheckConsistency(); if (freeList != PageBlock.Sentinel) { uint blockIdx = freeList; DebugStub.Assert(GetBlock(blockIdx)->IsLinked(freeList)); uint freePage = GetBlock(blockIdx)->FirstFreePage(); MarkPageInBlockUsed(blockIdx, freePage); ulong physPage = ((ulong)blockIdx * (ulong)PageBlock.PagesPerBlock) + freePage; ulong physAddr = (ulong)MemoryManager.PageSize * physPage; return new PhysicalAddress(physAddr); } DebugStub.WriteLine("** Physical memory exhausted! **"); return PhysicalAddress.Null; } finally { CheckConsistency(); Unlock(iflag); } }
internal override Allocation *MoveEndpoint(SharedHeap fromHeap, SharedHeap toHeap, Process newOwner) { DebugStub.Assert(fromHeap == toHeap); // Careful about the order. // Since we don't know if this is a release (current process owns it) // or an acquire (current process does not necessarily own it), we // have to bypass the owner check here. int processId = newOwner.ProcessId; this.ProcessId = processId; this.OwnerPrincipalHandle = new PrincipalHandle(newOwner.Principal.Val); // Don't check for delegation here since this is for kernel calls on // moving endpoints to SIPs. Delegation should not be involved. // The following should not be necessary, but just in case: this.OwnerDelegationState = DelegationState.None; Allocation.SetOwnerProcessId(this.endpointAlloc, processId); Allocation.SetOwnerProcessId(this.peerEp, processId); Monitoring.Log(Monitoring.Provider.EndpointCore, (ushort)EndpointCoreEvent.TransferToProcess, 0, (uint)ChannelId, (uint)processId, 0, 0, 0); return(this.endpointAlloc); }
internal unsafe void Unlink(ref uint listHead) { DebugStub.Assert(IsLinked(listHead)); if (prevIdx != Sentinel) { DebugStub.Assert(GetBlock(prevIdx)->nextIdx == Index, "PhysicalPages.PageBlock.Unlink: inconsistent prev->next"); GetBlock(prevIdx)->nextIdx = nextIdx; } else { // We are the list head. DebugStub.Assert(listHead == Index, "PhysicalPages.PageBlock.Unlink: inconsistent head"); listHead = nextIdx; } if (nextIdx != Sentinel) { DebugStub.Assert(GetBlock(nextIdx)->prevIdx == Index, "PhysicalPages.PageBlock.Unlink: inconsistent next->prev"); GetBlock(nextIdx)->prevIdx = prevIdx; } nextIdx = Sentinel; prevIdx = Sentinel; }
private void UpdateCursor(bool newVisibleState) { IoResult result; if (newVisibleState != cursorVisible) { byte cgaStart = 32; // Cursor off if (newVisibleState) { cgaStart = (byte)(64 + cursorStartLine); // Cursor on } result = indexRegister.Write8NoThrow(CGA_CURSOR_START); DebugStub.Assert(IoResult.Success == result); result = dataRegister.Write8NoThrow(cgaStart); DebugStub.Assert(IoResult.Success == result); cursorVisible = newVisibleState; } if (newVisibleState) { // Write cursor location result = indexRegister.Write8NoThrow(CGA_CURSOR_MSB); DebugStub.Assert(IoResult.Success == result); result = dataRegister.Write8NoThrow((byte)(cursor >> 8)); DebugStub.Assert(IoResult.Success == result); result = indexRegister.Write8NoThrow(CGA_CURSOR_LSB); DebugStub.Assert(IoResult.Success == result); result = dataRegister.Write8NoThrow((byte)(cursor & 0xff)); DebugStub.Assert(IoResult.Success == result); } }
public static unsafe bool GetFixedIoMemoryRange(uint range, out byte *data, out uint size, out bool readable, out bool writable) { bool ret = false; data = null; size = 0; readable = false; writable = false; IoConfig config = Thread.CurrentProcess.IoConfig; if (config != null && config.FixedRanges.Length > range) { IoMemoryRange imr = config.FixedRanges[range] as IoMemoryRange; if (imr != null) { data = (byte *)imr.PhysicalAddress.Value; DebugStub.Assert(data != null); size = (uint)imr.Length; readable = imr.Readable; writable = imr.Writable; ret = true; } } Tracing.Log(Tracing.Debug, "DeviceService.GetFixedIoMemoryRange(range={0}, out data={1:x8}, out size={2})", range, (UIntPtr)data, size); return(ret); }
private TCP MatchTCPSession(IPv4 srcAddress, ushort srcPort, IPv4 destAddress, ushort destPort, byte hash) { ChainedHashNode chainedHashNode = chainedHash[hash]; VTable.Assert(chainedHashNode != null); TCP tcpSession = chainedHashNode.sideCache; if ((tcpSession != null) && IsTCPSessionMatch(tcpSession, srcAddress, srcPort, destAddress, destPort)) { DebugPrint("Found TCP session in cache\n"); return(tcpSession); } tcpSession = null; LinkedListNode currentNode = chainedHashNode.linkedList.head; int numMatches = 0; while (currentNode != null) { TCP tmpTcpSession = currentNode.theObject as TCP; DebugStub.Assert(tmpTcpSession != null); VTable.Assert(tmpTcpSession != null); numMatches++; if (IsTCPSessionMatch(tmpTcpSession, srcAddress, srcPort, destAddress, destPort)) { DebugPrint("Found TCP session -- {0} matches required\n", numMatches); chainedHashNode.sideCache = tmpTcpSession; tcpSession = tmpTcpSession; break; } currentNode = currentNode.nxt; } return(tcpSession); }
internal static AccessPermission Get(uint descriptor) { DebugStub.Assert(IsType.Get(descriptor, L1.SectionType) || IsType.Get(descriptor, L1.SupersectionType)); return((AccessPermission)((descriptor & L1.ApMask) >> L1.ApRoll)); }
// Free a single physical page internal unsafe static void FreePage(PhysicalAddress addr) { bool iflag = Lock(); try { CheckConsistency(); ulong pageNum = MemoryManager.PagesFromBytes(addr.Value); uint blockIdx = (uint)(pageNum / (ulong)PageBlock.PagesPerBlock); uint pageIdx = (uint)(pageNum % (ulong)PageBlock.PagesPerBlock); PageBlock* thisBlock = GetBlock(blockIdx); bool wasFull = thisBlock->Full; thisBlock->MarkAsFree(pageIdx); if (wasFull) { // This block now has a page available; put it on the // free list DebugStub.Assert(!thisBlock->IsLinked(freeList)); thisBlock->Link(ref freeList); } } finally { CheckConsistency(); Unlock(iflag); } }
internal static uint Get(uint descriptor) { DebugStub.Assert(IsType.Get(descriptor, L1.CoarsePageTableType) || IsType.Get(descriptor, L1.SectionType) || IsType.Get(descriptor, L1.FinePageTableType)); return((descriptor & L1.DomainMask) >> L1.DomainRoll); }
// pageIdx specifies a page within this block // (zero is the first, PagesPerBlock-1 is the last) internal unsafe void MarkAsUsed(uint pageIdx) { CheckConsistency(); fixed( uint *pBeforeRegions = &blockMap ) { uint* pRegions = pBeforeRegions; // Point just before regions pRegions++; // Advance to the first region word uint regionIdx = pageIdx / 32; uint bitIdx = pageIdx % 32; DebugStub.Assert(pageIdx < PagesPerBlock, "PhysicalPages.PageBlock.MarkAsUsed: Bad page index"); DebugStub.Assert(!PageInUse(pageIdx), "PhysicalPages.PageBlock.MarkAsUsed: Page already in use"); DebugStub.Assert(!RegionFull(regionIdx), "PhysicalPages.PageBlock.MarkAsUsed: Region already full"); // Mark the page used in its subregion pRegions[regionIdx] |= ((uint)1 << (int)bitIdx); // If our whole subregion is full, mark the blockMap if (pRegions[regionIdx] == FullRegion) { blockMap |= ((uint)1 << (int)regionIdx); } } CheckConsistency(); }
/////////////////////////////////////////////////////////////////////// // // Tx buffer operations // internal void PopulateTsmtBuffer(PacketFifo fromUser) { DebugStub.Assert(this.ioRunning); // since no transmit interrupts are sent, we must check for // transmission events here if (txRingBuffer.NewTransmitEvent()) { NicEventType ev = NicEventType.TransmitEvent; if (eventRelay != null) { eventRelay.ForwardEvent(ev); } } using (txRingBuffer.thisLock.Lock()) { while (fromUser.Count > 0) { Packet packet = fromUser.Pop(); txRingBuffer.LockedPushTsmtBuffer(packet); } // update hardware tail pointer // so that hardware knows it has new packets to transmit Write32(Register.TSMT_DESC_TAIL, txRingBuffer.Head); // sw head is hw tail } }
// Illegal to call this on a full block. internal unsafe uint FirstFreePage() { DebugStub.Assert(!Full, "PhysicalPages.PageBlock.FirstFreePage: Block already full"); // Look for a clear bit in the region map for (int i = 0; i < RegionsPerBlock; i++) { if ((blockMap & (uint)((uint)1 << i)) == 0) { // This region is available. Look // for a free page in the specific // region. fixed (uint* pBeforeRegions = &blockMap) { uint* pRegion = pBeforeRegions + i + 1; for (int j = 0; j < 32; j++) { if ((*pRegion & ((uint)1 << j)) == 0) { // This page is free. return ((uint)i * 32) + (uint)j; } } } } } // If we're not full, we should never get here. Kernel.Panic("Inconsistency in PhysicalPages.PageBlock.FirstFreePage()"); return 0; }
internal static unsafe FreeNode *Create(PhysicalHeap *inHeap, UIntPtr addr, UIntPtr pages) { DebugStub.Assert(addr >= inHeap->startAddr); DebugStub.Assert((addr + (pages * MemoryManager.PageSize)) <= inHeap->heapLimit); FreeNode *node = (FreeNode *)addr; // This had better be a free page in the main table DebugStub.Assert(inHeap->PageWord(inHeap->PageIndex(addr)) == FreePage, "Creating a FreeNode for non-free page {0:x}", __arglist(addr)); node->signature = FreeNode.Signature; node->bytes = pages * MemoryManager.PageSize; node->prev = null; node->next = null; node->last = null; if (pages > 1) { node->last = LastNode.Create(inHeap, addr, node); } return(node); }
public override void SetNextInterrupt(TimeSpan delta) { #if VERBOSE DebugStub.WriteLine("Timer.SetNextInterrupt({0})", __arglist(delta.Ticks)); #endif DebugStub.Assert(Processor.InterruptsDisabled()); DebugStub.Assert(delta >= minInterruptInterval); DebugStub.Assert(delta <= maxInterruptInterval); bool iflag = Processor.DisableInterrupts(); try { // NB: cast is safe as (delta <= MaxInterruptInterval) uint timerIntervals = (uint)((delta.Ticks * Omap3430_TIMER1_Freq) / (1000 * 1000 * 10)); uint count = (0xffffffff - timerIntervals) + 1; Write(tldr, count); SetPeriodic(); SetInterruptEnabled(true); Start(); interruptPending = true; } finally { Processor.RestoreInterrupts(iflag); } }
public void GetReceivedPackets(Queue !outQueue) { lock (this) { DebugStub.Assert(rxAvailable >= 0 && rxAvailable <= LoopbackAdapter.RingSize); // Move Receive packets to 'outQueue'. Object packet; while (rxAvailable > 0 && (packet = rxBuffer.Dequeue()) != null) { outQueue.Enqueue(packet); txDeliveryComplete++; rxAvailable--; } DebugStub.Assert(rxAvailable >= 0 && rxAvailable <= LoopbackAdapter.RingSize); DebugStub.Assert( txDeliveryComplete <= LoopbackAdapter.RingSize); DebugPrint("Loopback: GetReceivedPackets() -> {0}\n", __arglist(outQueue.Count)); DebugPrintStatus(); readEvent.Reset(); writeEvent.Set(); } }
Set(ref uint descriptor, uint mask, int roll, uint value) { DebugStub.Assert((mask >> roll) >= value); descriptor &= mask; descriptor |= value << roll; }
public static void SetUdpChecksum(Bytes buffer, Bytes payload, int ipOffset, ushort udplength) { // sum IP pseudo ushort ipPayloadSize = 0; ushort headerSum = IpHeader.SumPseudoHeader(buffer, ipOffset, ref ipPayloadSize); DebugStub.Assert(udplength == ipPayloadSize); // now add it to the udp header + data int ipHeaderSize = (buffer[ipOffset] & 0xf) * 4; int udpOffset = ipOffset + ipHeaderSize; ushort udpsum = IpHeader.SumShortValues(buffer, ipOffset + IpHeader.Size, UDPHeader.Size); DebugStub.Assert(buffer[udpOffset + 6] == 0); DebugStub.Assert(buffer[udpOffset + 7] == 0); ushort payloadSum = IpHeader.SumShortValues(payload, 0, payload.Length); ushort hdrSum = IpHeader.SumShortValues(headerSum, udpsum); ushort chksum; chksum = (ushort)~( IpHeader.SumShortValues(hdrSum, payloadSum) ); buffer[udpOffset + 6] = (byte)(chksum >> 8); buffer[udpOffset + 7] = (byte)(chksum & 0xff); }
internal static uint Get(uint descriptor) { DebugStub.Assert(IsType.Get(descriptor, L1.SectionType) || IsType.Get(descriptor, L1.SupersectionType)); return((descriptor & L1.TexMask) >> L1.TexRoll); }
private void Unmask(byte irq) { DebugStub.Assert(Processor.InterruptsDisabled()); ushort newMask = (ushort)(irqMask & ~(1 << irq)); if (newMask != irqMask) { #if DEBUG_DISPATCH_IO DebugStub.WriteLine("-- Unmask IRQs: old={0:x4} new={1:x4}", __arglist(irqMask, newMask)); #endif irqMask = newMask; IoResult result; result = pic1MaskPort.Write8NoThrow((byte)(irqMask >> 8)); DebugStub.Assert(IoResult.Success == result); result = pic0MaskPort.Write8NoThrow((byte)(irqMask & 0xff)); DebugStub.Assert(IoResult.Success == result); #if PIC_DEBUG byte mask0; result = pic0MaskPort.Read8(out mask0); DebugStub.Assert(IoResult.Success == result); byte mask1; result = pic1MaskPort.Read8(out mask1); DebugStub.Assert(IoResult.Success == result); DebugStub.Print("PIC Mask: {0:x2}{1:x2}\n", __arglist(mask1, mask0)); #endif } }
internal static void Set(ref uint descriptor, AccessPermission ap) { DebugStub.Assert(IsType.Get(descriptor, L1.SectionType) || IsType.Get(descriptor, L1.SupersectionType)); descriptor = ((descriptor & ~L1.ApMask) | ((uint)ap) << L1.ApRoll); }
// // Get and map multiple new pages. On failure, no pages are allocated. // internal static bool CommitAndMapRange(UIntPtr virtualAddr, UIntPtr limitAddr, ProtectionDomain inDomain) { DebugStub.Assert(IsPageAligned(virtualAddr)); DebugStub.Assert(IsPageAligned(limitAddr)); for (UIntPtr step = virtualAddr; step < limitAddr; step += PageSize) { if (!CommitAndMapNewPage(step, inDomain)) { // Uh oh; we failed. for (UIntPtr unmapStep = virtualAddr; unmapStep < virtualAddr; unmapStep += PageSize) { UnmapAndReleasePage(unmapStep); } return(false); } } return(true); }
private void Unmask(byte irq) { DebugStub.Assert(Processor.InterruptsDisabled()); uint n = irq / 32u; uint bit = 1u << (irq % 32); #if DEBUG_DISPATCH_IO DebugStub.WriteLine("PIC.Unmask({0}) => {1:x8}", __arglist(irq, bit)); #endif uint mask = GetMaskWord(n); if ((mask & bit) != 0) { #if DEBUG_DISPATCH_IO DebugStub.WriteLine("-- Unmask IRQs [{0}: old={1:x8} new={2:x8}", __arglist(n, mask, mask & ~bit)); #endif #if false // Enable this to set interrupt without hardware. IoResult result = IoResult.Success; intcps_mir_clear[n].Write32NoThrow(bit, ref result); intcps_isr_set[n].Write32NoThrow(bit, ref result); DebugStub.Assert(IoResult.Success == result); #endif SetMaskWord(n, mask & ~bit); #if PIC_DEBUG DumpBits("-- PIC interrupt mask: {2:x8}{1:x8}{0:x8}", intcps_mir); #endif } }