Exemple #1
0
void segv_sigaction(int signum, siginfo_t* sinfo, void * p){
  // Check signal
  if (SIGSEGV != signum) {
    printf ("Bad handler for bad signal...\n");
    exit (1);
  }


  // Check if fault is from managed segment
  if(sinfo->si_addr < start_addr || sinfo->si_addr >= size*PAGESIZE+start_addr){
    printf("Segfault somewhere else... good luck...\n");
    printf(" Hint: run the debugger and set a breakpoint for this line\n");
    exit(1);
  }

  // Check cause of fault
  if(sinfo->si_code != SEGV_ACCERR){
    printf("Object not mapped...\n");
    printf(" Hint: run the debugger and set a breakpoint for this line\n");
    exit(1);
  }

  // Find out virtual page in fault
  page_virt pv=PAGEOF(sinfo->si_addr);

  // If not invalid then setDirtyBit
  // Allow read, but wait until page has been loaded...
  if(mmu_array[pv].pp != INVALID){
    if(!mmu_array[pv].accessed){
      struct timeval delay;
      struct timeval now;
      gettimeofday(&now,NULL);
      timeradd(&delay,&delay_load,&delay);
      timersub(&delay,&now,&delay);
      if(delay.tv_sec >= 0){
    	  int UNUSED r;
    	  struct timespec s;
    	  TV2TS(delay,s);
    	  //do{
    	  //	  r=nanosleep(&s,&s);
    	  //  }while(r < 0 && errno == EINTR);
      }
      mmu_setAccessedBit(pv);
    }else{
      mmu_setDirtyBit(pv);
    }
  }else{
  // Else call page fault handler
	  stats_faults++;
    page_fault_handler(pv);
  }

  // Check that translation has been added
  if(mmu_array[pv].pp == INVALID){
    printf("Page fault handler did not update MMU...\n");
    exit(1);
  }
}
Exemple #2
0
static enum armv2_status load_section( struct armv2 *cpu, uint32_t start, uint32_t end, FILE *f, ssize_t *size_out ) {
    uint32_t section_length = 0;
    ssize_t  read_bytes     = 0;
    ssize_t size = *size_out;

    if(0 != INPAGE(start)) {
        //We only want to start loading sections in at page boundaries
        LOG("Error starting section off page boundary\n");
        return ARMV2STATUS_INVALID_PAGE;
    }

    uint32_t page_num = PAGEOF(start);

    read_bytes = fread(&section_length, sizeof(section_length), 1, f);
    if(read_bytes != 1) {
        LOG("Error reading opening length\n");
        return ARMV2STATUS_IO_ERROR;
    }

    section_length = htonl( section_length );

    size -= sizeof(section_length);

    if( section_length > (end - start) ) {
        LOG("Error, section length of %08x would take us past end %08x\n", section_length, end );
        return ARMV2STATUS_IO_ERROR;
    }

    if( section_length > size ) {
        LOG("Error, not enough data for section length 0x%x (0x%zx bytes remaining)\n", section_length, size);
        return ARMV2STATUS_IO_ERROR;
    }

    size -= section_length;

    while(section_length > 0) {
        size_t to_read = section_length > PAGE_SIZE ? PAGE_SIZE : section_length;
        read_bytes = fread(cpu->page_tables[page_num++]->memory, 1, to_read,f);
        if(read_bytes != to_read) {

            if(read_bytes != section_length) {
                LOG("Error %d %zd %zd %d\n",page_num, read_bytes, size, section_length);
                return ARMV2STATUS_IO_ERROR;
            }
        }
        section_length -= to_read;
    }
    
    *size_out = size;

    return ARMV2STATUS_OK;
}
bool	FLASHDRVR::write_page(const unsigned addr, const unsigned len,
		const unsigned *data, const bool verify_write) {
	DEVBUS::BUSW	buf[SZPAGE];

	assert(len > 0);
	assert(len <= PGLEN);
	assert(PAGEOF(addr)==PAGEOF(addr+len-1));

	if (len <= 0)
		return true;

	// Write the page
	m_fpga->writeio(R_ICONTROL, ISPIF_DIS);
	m_fpga->clear();
	m_fpga->writeio(R_ICONTROL, ISPIF_EN);
	printf("Writing page: 0x%08x - 0x%08x\n", addr, addr+len-1);
	m_fpga->writeio(R_QSPI_EREG, DISABLEWP);
	m_fpga->writei(addr, len, data);

	// If we're in high speed mode and we want to verify the write, then
	// we can skip waiting for the write to complete by issueing a read
	// command immediately.  As soon as the write completes the read will
	// begin sending commands back.  This allows us to recover the lost 
	// time between the interrupt and the next command being received.
	if ((!HIGH_SPEED)||(!verify_write)) {
		flwait();
	} if (verify_write) {
		// NOW VERIFY THE PAGE
		m_fpga->readi(addr, len, buf);
		for(unsigned i=0; i<len; i++) {
			if (buf[i] != data[i]) {
				printf("\nVERIFY FAILS[%d]: %08x\n", i, i+addr);
				printf("\t(Flash[%d]) %08x != %08x (Goal[%08x])\n", 
					i, buf[i], data[i], i+addr);
				return false;
			}
		}
	} return true;
}
Exemple #4
0
enum armv2_status map_memory(struct armv2 *cpu, uint32_t device_num, uint32_t start, uint32_t end) {
    uint32_t page_pos    = 0;
    uint32_t page_start  = PAGEOF(start);
    uint32_t page_end    = PAGEOF(end);
    struct hardware_mapping hw_mapping = {0};
    if(NULL == cpu || end <= start) {
        return ARMV2STATUS_INVALID_ARGS;
    }
    if(device_num >= cpu->num_hardware_devices) {
        return ARMV2STATUS_NO_SUCH_DEVICE;
    }
    if(NULL == cpu->hardware_devices[device_num]) {
        return ARMV2STATUS_INVALID_CPUSTATE;
    }
    if(start&PAGE_MASK                  ||
       end  &PAGE_MASK                  ||
       page_start == 0                  ||
       page_end == 0                    ||
       page_start >= NUM_PAGE_TABLES    ||
       page_end >= NUM_PAGE_TABLES
       //page_start == INTERRUPT_PAGE_NUM ||
       //page_end == INTERRUPT_PAGE_NUM  ) {
        ) {
        return ARMV2STATUS_INVALID_ARGS;
    }
    //First we need to know if all of the requested memory is available for mapping. That means
    //it must not have been mapped already, and it may not be the zero page
    for(page_pos = page_start; page_pos < page_end; page_pos++) {
        struct page_info *page;
        if(page_pos >= NUM_PAGE_TABLES) { // || page_pos == INTERRUPT_PAGE_NUM) {
            return ARMV2STATUS_MEMORY_ERROR;
        }
        page = cpu->page_tables[page_pos];
        if(page == NULL) {
            //That's OK, that means this page is currently completely unmapped. We can make a page just for this
            continue;
        }
        if(page->read_callback || page->write_callback || page->read_byte_callback || page->write_byte_callback) {
            return ARMV2STATUS_ALREADY_MAPPED;
        }
    }
    hw_mapping.device = cpu->hardware_devices[device_num];
    //If we get here then the entire range is free, so we can go ahead and fill it in
    for(page_pos = page_start; page_pos < page_end; page_pos++) {
        struct page_info *page = cpu->page_tables[page_pos];

        if(NULL == page) {
            //we need a new page
            page = calloc(1, sizeof(struct page_info));
            if(NULL == page) {
                //I don't think I'm leaving anything untidied up by returning here
                return ARMV2STATUS_MEMORY_ERROR;
            }
            page->flags = (PERM_READ|PERM_EXECUTE|PERM_WRITE);
            page->memory = NULL;
            if(hw_mapping.device) {
                page->mapped_device = hw_mapping.device->extra;
            }
            cpu->page_tables[page_pos] = page;
        }
        //Already checked everything's OK, and we're single threaded, so this should be ok I think...
        /* LOG("Setting page_pos %x to callbacks %p %p flags %x\n", */
        /*     page_pos, */
        /*     hw_mapping.device->read_callback, */
        /*     hw_mapping.device->write_callback, */
        /*     hw_mapping.device->read_byte_callback, */
        /*     hw_mapping.device->write_byte_callback); */
        page->read_callback  = hw_mapping.device->read_callback;
        page->write_callback = hw_mapping.device->write_callback;
        page->read_byte_callback  = hw_mapping.device->read_byte_callback;
        page->write_byte_callback = hw_mapping.device->write_byte_callback;
    }

    hw_mapping.start = start;
    hw_mapping.end   = end;
    hw_mapping.flags = 0; //maybe use these later
    add_mapping(&(cpu->hw_mappings),&hw_mapping);

    return ARMV2STATUS_OK;
}
bool	FLASHDRVR::write(const unsigned addr, const unsigned len,
		const unsigned *data, const bool verify) {
	// Work through this one sector at a time.
	// If this buffer is equal to the sector value(s), go on
	// If not, erase the sector

	// m_fpga->writeio(R_QSPI_CREG, 2);
	// m_fpga->readio(R_VERSION);	// Read something innocuous
	// m_fpga->writeio(R_QSPI_SREG, 0);
	// m_fpga->readio(R_VERSION);	// Read something innocuous

	for(unsigned s=SECTOROF(addr); s<SECTOROF(addr+len+SECTORSZ-1); s+=SECTORSZ) {
		// printf("IN LOOP, s=%08x\n", s);
		// Do we need to erase?
		bool	need_erase = false;
		unsigned newv = 0; // (s<addr)?addr:s;
		{
			DEVBUS::BUSW	*sbuf = new DEVBUS::BUSW[SECTORSZ];
			const DEVBUS::BUSW *dp;
			unsigned	base,ln;
			base = (addr>s)?addr:s;
			ln=((addr+len>s+SECTORSZ)?(s+SECTORSZ):(addr+len))-base;
			m_fpga->readi(base, ln, sbuf);

			dp = &data[base-addr];
			for(unsigned i=0; i<ln; i++) {
				if ((sbuf[i]&dp[i]) != dp[i]) {
					printf("\nNEED-ERASE @0x%08x ... %08x != %08x (Goal)\n", 
						i+base-addr, sbuf[i], dp[i]);
					need_erase = true;
					newv = i+base;
					break;
				} else if ((sbuf[i] != dp[i])&&(newv == 0)) {
					// if (newv == 0)
						// printf("MEM[%08x] = %08x (!= %08x (Goal))\n",
							// i+base, sbuf[i], dp[i]);
					newv = i+base;
				}
			}
		}

		if (newv == 0)
			continue; // This sector already matches

		// Just erase anyway
		if ((need_erase)&&(!erase_sector(s, verify))) {
			printf("SECTOR ERASE FAILED!\n");
			return false;
		} else if (!need_erase)
			printf("NO ERASE NEEDED\n");
		else {
			printf("ERASING SECTOR %08x\n", s);
			newv = (s<addr) ? addr : s;
		}
		for(unsigned p=newv; (p<s+SECTORSZ)&&(p<addr+len); p=PAGEOF(p+PGLEN))
			if (!write_page(p, (p+PGLEN<addr+len)
				?((PAGEOF(p)!=PAGEOF(p+PGLEN-1))?(PAGEOF(p+PGLEN-1)-p):PGLEN)
				:(addr+len-p), &data[p-addr]), verify) {
				printf("WRITE-PAGE FAILED!\n");
				return false;
		}
	}

	m_fpga->writeio(R_QSPI_EREG, 0); // Re-enable write protection

	return true;
}