Ejemplo n.º 1
0
int main()
{
#ifndef ONLINE_JUDGE
	//freopen("all.in", "r", stdin);
	//freopen("out", "w", stdout);
#endif

	int i, ii, j, ans;

	while(scanf("%d%d", &k, &n) && n && k) {
		for(i = 1; i <= n; i ++){
			scanf("%s", a[i].name);
			for(j = 1; j <= k; j ++)
				scanf("%d", &a[i].books[j]);
		}

		/*for books*/
		for (ans = 0, i = 1; i <= n; i ++)
		{
			for (top = 0, ii = 1; ii <= n; ii ++) for (j = 1; j <= k; j ++)
				if (a[ii].books[j] == i) q[top++] = ii;
			if (vio(i)) ans ++;
		}

		if (ans == 0) printf ("NO PROBLEMS FOUND\n");
		else if (ans == 1) printf ("1 PROBLEM FOUND\n");
		else printf ("%d PROBLEMS FOUND\n", ans);
	}
	return 0;
}
Ejemplo n.º 2
0
std::pair<bool, bool>
MemoryType::checkAndMergeMemType(size_t ofs, const RsType* type)
{
    if (typedata.size() == 0) // no types registered yet
        return mtyFailed();

    size_t            newStart = ofs;
    size_t            newLength = type->getByteSize();

    if ( diagnostics::message(diagnostics::memory) )
    {
      std::stringstream msg;

      msg << "++ checkAndMergeMemType ofs: " << newStart << " (base = " << startAddress << ")"
          << "   length: " << newLength << std::endl;

      RuntimeSystem::instance().printMessage( msg.str() );
    }

    // Get a range of entries which overlap with [newStart,newTiEnd)
    TiIterPair res = ::getOverlappingTypeInfos(typedata, newStart, newLength);
    TiIter     itLower = res.first;
    TiIter     itUpper = res.second;

    // Case 0: There are types registered, but not ϵ [newStart, newTiEnd)
    if (itLower == itUpper)
      return mtyFailed();

    //  Case 1: New entry is overlapped by one old entry,
    //  i.e. [itLower,itUpper) contains only one entry
    TiIter     incrementedLower = itLower;
    ++incrementedLower;

    if (incrementedLower == itUpper)
    {
        const RsType*  oldType = itLower->second;
        size_t         oldStart = itLower->first;
        size_t         oldLength = oldType->getByteSize();
        std::ptrdiff_t diff = oldStart - newStart;

        // was: if( (oldStart <= newStart) && (oldTiEnd >= newTiEnd) )
        if ((diff <= 0) && (newLength <= (diff + oldLength)))
        {
            //Check if new entry is consistent with old one
            bool new_type_ok = oldType->checkSubtypeRecursive( newStart - oldStart, type );

            if( !new_type_ok )
            {
                // \todo \ofs startAddress.local + newStart
                RuntimeViolation vio(RuntimeViolation::INVALID_TYPE_ACCESS, composeVioMessage(startAddress.local + newStart, newLength, type, *this) );

                vio.descStream() << "Previously registered Type completely overlaps new Type in an inconsistent way:"
                                 << std::endl
                                 << "Containing Type " << oldType->getName()
                                 << " (" << oldStart << ","
                                 << (oldStart + oldLength) << ")  base = " << startAddress
                                 << std::endl;

                RuntimeSystem::instance().violationHandler(vio);
                return mtyFailed();
            }
            else
            {
                // successful, no need to add because the type is already contained in bigger one
                // effectively type has already been “merged”.
                return mtyNoUpdate();
            }
        }
    }

    // Case 2: Iterate over overlapping old types and check consistency
    for(TypeData::iterator i = itLower; i != itUpper; ++i )
    {
        const RsType*  curType = i->second;
        size_t         curStart = i->first;
        size_t         curLength = curType->getByteSize();
        std::ptrdiff_t diff = curStart - newStart;

        // std::cout << "  >> " << diff << " #" << newLength << "  #" << curLength << std::endl;

        // was: if ((curStart < newStart) || (newTiEnd < curEnd))
        if ((diff < 0) || (newLength < (diff + curLength)))
        {
            // \todo \ofs startAddress.local + newStart
            RuntimeViolation vio(RuntimeViolation::INVALID_TYPE_ACCESS, composeVioMessage(startAddress.local + newStart, newLength, type, *this) );

            vio.descStream() << "Previously registered Type overlaps new Type in an inconsistent way:"
                             << std::endl
                             << "Overlapping Type " << curType->getName()
                             << " (" << curStart << "," << (curStart + curLength) << ")  base = " << startAddress
                             << std::endl;
            RuntimeSystem::instance().violationHandler(vio);
            return mtyFailed();
        }

        const RsType* sub = type->getSubtypeRecursive(diff /*curStart - newStart*/, curLength);

        if (sub != curType)
        {
            // \todo \ofs startAddress.local + newStart
            RuntimeViolation vio(RuntimeViolation::INVALID_TYPE_ACCESS, composeVioMessage(startAddress.local + newStart, newLength, type, *this) );

            vio.descStream() << "Newly registered Type completely overlaps a previous registered Type in an inconsistent way:"
                             << std::endl
                             << "Overlapping Type " << curType->getName()
                             << " (" << curStart << "," << (curStart + curLength) << ")  base = " << startAddress
                             << std::endl;

            RuntimeSystem::instance().violationHandler(vio);
            return mtyFailed();
        }
    }
    //All consistent - old typeInfos are replaced by big new typeInfo (merging)
    typedata.erase(itLower, itUpper);
    insert( typedata, TypeData::value_type(ofs, type) );

    // if we have knowledge about the type in memory, we also need to update the
    // information about "dereferentiable" memory regions i.e. pointer

    const long     blocksize = blockSize();
    Location       addr = ::add(startAddress, ofs, blocksize);
    RuntimeSystem& rs = rtedRTS(this);

    rs.getPointerManager().createPointer(addr, type, blocksize);
    return mtyMerged();
}
int main()
{
	VirtioDriver vio(VIRTIO_0_BASE);
	vio.init();

	kout << "Magic value is " << Hex(vio.reg32<VirtioDriver::V2_MagicValue>()) << "\n";
	kout << "Version = " << vio.reg32<VirtioDriver::V2_Version>() << "\n";
	kout << "VendorID = " << Hex(vio.reg32<VirtioDriver::V2_VendorID>()) << "\n";
	kout << "DeviceID = " << Hex(vio.reg32<VirtioDriver::V2_DeviceID>()) << "\n";
	kout << "HostFeatures = " << Hex(vio.reg32<VirtioDriver::V1_HostFeatures>()) << "\n";
	kout << "GuestPageSize = " << Hex(vio.reg32<VirtioDriver::V1_GuestPageSize>()) << "\n";
	kout << "DeviceStatus = " << Hex(vio.reg32<VirtioDriver::V1_Status>()) << "\n";
	kout << "QueueNumMax = " << vio.reg32<VirtioDriver::V1_QueueNumMax>() << "\n";


	auto blkConf = vio.regcopy<VirtioBlockConfig,VirtioDriver::V1_Config>();
	blkConf.dump();

//	return 0;

	// 至少包含2个对齐的PAGE
	char queueBuffer[VirtioDriver::PAGE_SIZE_4KB*3];
	// 对齐处的地址
	uint64_t pageAddr = alignAhead(reinterpret_cast<uint64_t>(queueBuffer),VirtioDriver::PAGE_SIZE_4KB);

	// legacy需要3个,[0]=8byte,3fields, [1]=data,[2]=1byte status
	size_t descrNum = 4;
	uint16_t startDescrIndex=1;
	constexpr size_t readBytes =
//			3
			// 512*3-1  // invalid
			512*3 // 必须是512的n倍
			;
	// qsize
	// mem_size
	//
	VirtioQueueLayout vq(reinterpret_cast<void*>(pageAddr),descrNum,VirtioDriver::USED_RING_ALIGNMENT);

	auto memSize = vq.memSize();
	kout << "virtqueue memSize = " << memSize << "\n";
	// 应当清0
	std::memset(vq.queueBase(), 0, memSize);

	// reqeust
	size_t blkNum = 1;
	size_t reqBufSize = VirtioBlockRequestRef::memSize(blkNum);
	if(reqBufSize >= readBytes + 512)
	{
		kout << FATAL << "req size overflows\n";
		return 1;
	}

	// 至少包含readBytes个
	char reqBuf[readBytes+512];

	VirtioBlockRequestRef vreq(reqBuf,blkNum,VirtioBlockRequestRef::REQ_IN,0);
	const char * invalidStr = "if you see this, then it is invalid\n";
	std::memcpy(vreq.data(),invalidStr,std::strlen(invalidStr));


	VirtioQueueDescriptor * descs[3];
	vq.allocateDescriptros(descs, 3);
	vq.chainDescriptors(descs, 3);
//	descs[0]

	// DW = DeviceWriteOnly,DR = DeviceReadOnly
	// [0]=header,DR,[1]=status,DW[2]=empty buffer,DW
	// or
	// [0] = header + status + empty buffer, DW
	// 前一个用于legacy模式
	auto descTable = vq.descTable();
	new (&descTable[startDescrIndex]) VirtioQueueDescriptor(reinterpret_cast<uint64_t>(vreq.base()),16,bitOnes<VirtioQueueDescriptor::VIRTQ_DESC_F_NEXT>(),startDescrIndex+1);
	new (&descTable[startDescrIndex+1]) VirtioQueueDescriptor(descTable[startDescrIndex+1].addr() + 16,readBytes,bitOnes<VirtioQueueDescriptor::VIRTQ_DESC_F_NEXT,VirtioQueueDescriptor::VIRTQ_DESC_F_WRITE>(),startDescrIndex+2);
	new (&descTable[startDescrIndex+2]) VirtioQueueDescriptor(descTable[startDescrIndex+2].addr() + readBytes,1,bitOnes<VirtioQueueDescriptor::VIRTQ_DESC_F_WRITE>(),0);

	// 注意, old_idx和new_idx之间的差值就是本次请求的数目
	auto & avRef = vq.availRing();
	avRef.idx(1); //
	avRef.ring()[0]=startDescrIndex;// header
//	avRef.ring()[1]=startDescrIndex + 1;
	/*
	下面这些寄存器只写
	case VIRTIO_MMIO_DEVICE_FEATURES_SEL:
    case VIRTIO_MMIO_DRIVER_FEATURES:
    case VIRTIO_MMIO_DRIVER_FEATURES_SEL:
    case VIRTIO_MMIO_GUEST_PAGE_SIZE:
    case VIRTIO_MMIO_QUEUE_SEL:
    case VIRTIO_MMIO_QUEUE_NUM:
    case VIRTIO_MMIO_QUEUE_ALIGN:
    case VIRTIO_MMIO_QUEUE_NOTIFY:
    case VIRTIO_MMIO_INTERRUPT_ACK:

	// 下面这些寄存器只读
    case VIRTIO_MMIO_MAGIC_VALUE:
    case VIRTIO_MMIO_VERSION:
    case VIRTIO_MMIO_DEVICE_ID:
    case VIRTIO_MMIO_VENDOR_ID:
    case VIRTIO_MMIO_DEVICE_FEATURES:
    case VIRTIO_MMIO_QUEUE_NUM_MAX:
    case VIRTIO_MMIO_INTERRUPT_STATUS:

	 */
/*
 *
		The virtual queue is configured as follows:
		1. Select the queue writing its index (first queue is 0) to QueueSel.
		2. Check if the queue is not already in use: read QueuePFN, expecting a returned value of zero (0x0).
		3. Read maximum queue size (number of elements) from QueueNumMax. If the returned value is zero
		(0x0) the queue is not available.
		4. Allocate and zero the queue pages in contiguous virtual memory, aligning the Used Ring to an optimal boundary (usually page size). The driver should choose a queue size smaller than or equal to
		QueueNumMax.
		5. Notify the device about the queue size by writing the size to QueueNum.
		6. Notify the device about the used alignment by writing its value in bytes to QueueAlign.
		7. Write the physical number of the first page of the queue to the QueuePFN register.
 *
 *
 */
	vio.reg32<VirtioDriver::V1_QueueSel>() = 0; // set current
	vio.reg32<VirtioDriver::V1_QueueNum>()=descrNum; // set current queue size
	vio.reg32<VirtioDriver::V1_QueuePFN>() = pageAddr / VirtioDriver::PAGE_SIZE_4KB; // 设置PFN

	// notify index 0 completed
	vio.reg32<VirtioDriver::V1_QueueNotify>()=0; // which queue?

	// wait to complete
	delayCPU(1000*1000);

	kout << "=====read data is \n";
	kout.print(reinterpret_cast<const char*>(vreq.data()),readBytes);
	kout << "\n=================\n";

	/*

	 Historically, many drivers ignored the len value, as a result, many devices set len incorrectly. Thus, when
using the legacy interface, it is generally a good idea to ignore the len value in used ring entries if possible.
Specific known issues are listed per device type.

 	 对于block device,
 	 When using the legacy interface, transitional drivers SHOULD ignore the len value in used ring entries.
Note: Historically, some devices put the total descriptor length, or the total length of device-writable buffers
there, even when only the status byte was actually written.
	也就是说,legacy 模式下的len应当忽略
	在实践中,len返回的总是readBytes + 1,因此应当忽略。

	 */
	// 读取usedRing
	// 同样,old_idx和new_idx之间的差值也体现了本次完成的数目
	auto &usedRingRef = vq.usedRing();
	kout << "used ring idx = " << usedRingRef.idx() << "\n";
	kout << "ring[0]{id,len} = " << usedRingRef.ring()[0]._id  << "," << usedRingRef.ring()[0]._len<< "\n";
//	kout << "ring[1]{id,len} = " << usedRingRef.ring()[1]._id  << "," << usedRingRef.ring()[1]._len<< "\n";

	return 0;
}