Esempio n. 1
0
/* 
 * pgd3val: this is the value of init_mm.pgd[3] in a PV guest. It is optional.
 *          This to assist debug of modules in the guest. The kernel address 
 *          space seems is always mapped, but modules are not necessarily 
 *          mapped in any arbitraty guest cr3 that we pick if pgd3val is 0. 
 *          Modules should always be addressible if we use cr3 from init_mm. 
 *          Since pgd3val is already a pgd value, cr3->pgd[3], we just need to 
 *          do 2 level lookups.
 *
 * NOTE: 4 level paging works for 32 PAE guests also because cpu runs in IA32-e
 *       mode.
 * Returns: mfn for the given (pv guest) vaddr 
 */
static unsigned long 
dbg_pv_va2mfn(dbgva_t vaddr, struct domain *dp, uint64_t pgd3val)
{
    l4_pgentry_t l4e, *l4t;
    l3_pgentry_t l3e, *l3t;
    l2_pgentry_t l2e, *l2t;
    l1_pgentry_t l1e, *l1t;
    unsigned long cr3 = (pgd3val ? pgd3val : dp->vcpu[0]->arch.cr3);
    unsigned long mfn = cr3 >> PAGE_SHIFT;

    DBGP2("vaddr:%lx domid:%d cr3:%lx pgd3:%lx\n", vaddr, dp->domain_id, 
          cr3, pgd3val);

    if ( pgd3val == 0 )
    {
        l4t = mfn_to_virt(mfn);
        l4e = l4t[l4_table_offset(vaddr)];
        mfn = l4e_get_pfn(l4e);
        DBGP2("l4t:%p l4to:%lx l4e:%lx mfn:%lx\n", l4t, 
              l4_table_offset(vaddr), l4e, mfn);
        if ( !(l4e_get_flags(l4e) & _PAGE_PRESENT) )
        {
            DBGP1("l4 PAGE not present. vaddr:%lx cr3:%lx\n", vaddr, cr3);
            return INVALID_MFN;
        }

        l3t = mfn_to_virt(mfn);
        l3e = l3t[l3_table_offset(vaddr)];
        mfn = l3e_get_pfn(l3e);
        DBGP2("l3t:%p l3to:%lx l3e:%lx mfn:%lx\n", l3t, 
              l3_table_offset(vaddr), l3e, mfn);
        if ( !(l3e_get_flags(l3e) & _PAGE_PRESENT) )
        {
            DBGP1("l3 PAGE not present. vaddr:%lx cr3:%lx\n", vaddr, cr3);
            return INVALID_MFN;
        }
    }

    l2t = mfn_to_virt(mfn);
    l2e = l2t[l2_table_offset(vaddr)];
    mfn = l2e_get_pfn(l2e);
    DBGP2("l2t:%p l2to:%lx l2e:%lx mfn:%lx\n", l2t, l2_table_offset(vaddr),
          l2e, mfn);
    if ( !(l2e_get_flags(l2e) & _PAGE_PRESENT) ||
         (l2e_get_flags(l2e) & _PAGE_PSE) )
    {
        DBGP1("l2 PAGE not present. vaddr:%lx cr3:%lx\n", vaddr, cr3);
        return INVALID_MFN;
    }
    l1t = mfn_to_virt(mfn);
    l1e = l1t[l1_table_offset(vaddr)];
    mfn = l1e_get_pfn(l1e);
    DBGP2("l1t:%p l1to:%lx l1e:%lx mfn:%lx\n", l1t, l1_table_offset(vaddr),
          l1e, mfn);

    return mfn_valid(mfn) ? mfn : INVALID_MFN;
}
Esempio n. 2
0
/*
 * TWI Event & Data Interrupt Handler
 */
void TwEventIrq( void *arg)
{
    NUTTWIBUS *bus = arg;
    NUTTWIICB *icb = bus->bus_icb;
    I2C_TypeDef* I2Cx = (I2C_TypeDef*)bus->bus_base;
    uint32_t twsr1 = I2Cx->SR1;
    uint32_t twsr2 = I2Cx->SR2;
//    int i;

#if 0
    i=16;
    do {
        i--;
        DBGP1(1);
        DBGP2(twsr1&(1<<i));
        DBGP1(0);
    } while(i);
#endif

    if( twsr1 & I2C_SR1_SB) {
        /* Send Slave Address and direction bit */
        // TODO: 10-Bit Addressing
        I2Cx->DR = (icb->tw_mm_sla | icb->tw_mm_dir);
    }

    if( twsr2 & I2C_SR2_MSL)
    {
        DBGP1(1);
        /* Interface is in master mode */

        if( twsr1 & I2C_SR1_ADDR) {
            /*
             * This Section is called only after
             * Slave Address has been sent
             */
            if( icb->tw_mm_dir == MODE_WRITE) {
                /*
                 * Master Transmitter 1st Byte
                 */
                if( icb->tw_mm_iadrlen) {
                    /* we have to send a register address to the slave */
                    /* little-endian machine! */
                    I2Cx->DR = *icb->tw_mm_iadr--;
                    icb->tw_mm_iadrlen--;
                }
                else if( icb->tw_mm_txlen) {
                    /* we have to send data */
                    I2Cx->DR = *icb->tw_mm_txbuf++;
                    icb->tw_mm_txlen--;
                }

                /* If there was only one byte to send */
                if( (icb->tw_mm_txlen==0) && (icb->tw_mm_iadrlen==0)) {
                    /* Disable TXE Interrupt */
                    I2C_DIS_BUF(I2Cx);
                }
            }
            else {
                /*
                 * Master Receiver if only one byte awaited
                 */
                /* Check if only one byte to read */
                if( icb->tw_mm_rxlen == 1) {
                    /* Last byte awaited: send NACK and STOP */
                    I2C_NACK_STOP(I2Cx);
                }
            }
            goto TwEvExit;
        }


        /*
         * Master in transmission 2nd to last byte
         */
        if( (twsr1 & (I2C_SR1_TXE|I2C_SR1_BTF)) == I2C_SR1_TXE) {
            if( icb->tw_mm_iadrlen) {
                /* send next register address byte */
                /* little-endian machine! */
                I2Cx->DR = *icb->tw_mm_iadr--;
                icb->tw_mm_iadrlen--;
            }
            else if( icb->tw_mm_txlen) {
                /* send next data byte */
                I2Cx->DR = *icb->tw_mm_txbuf++;
                icb->tw_mm_txlen--;
            }
            /* Check if end of tx */
            if( (icb->tw_mm_txlen==0) && (icb->tw_mm_iadrlen==0)) {
                /* Nothing left to send */
                I2C_DIS_BUF(I2Cx);
            }
            goto TwEvExit;
        }

        /*
         * Master transmitted last byte
         */
        if( (twsr1 & (I2C_SR1_TXE|I2C_SR1_BTF)) == (I2C_SR1_TXE|I2C_SR1_BTF)) {
            /* Check if Write->Read transition */
            if( icb->tw_mm_rxlen) {
                /* Switch to read direction */
                icb->tw_mm_dir = MODE_READ;
                /* Issue a RESTART */
                I2C_RESTART(I2Cx);
                /* Enable Buffer Interrupt again */
                I2C_ENA_BUF(I2Cx);
            }
            else {
                /* We are complete: Clear ACK, send STOP */
                I2C_NACK_STOP(I2Cx);
                /* Disable EV_IT */
                I2C_DIS_EVT(I2Cx);
            }
            goto TwEvExit;
        }

        /*
         * Master is receiving
         */
        if( twsr1 & I2C_SR1_RXNE) {
            /* Read data */
            *icb->tw_mm_rxbuf++ = (uint8_t)I2Cx->DR;
            icb->tw_mm_rxlen--;
            if( icb->tw_mm_rxlen == 1) {
                /* Only one byte left to receive: Clear ACK, set STOP */
                I2C_NACK_STOP(I2Cx);
            }
            if( icb->tw_mm_rxlen == 0) {
                /* Only one byte left to receive: Clear ACK, set STOP */
                I2C_DIS_BUF(I2Cx);
                goto TwEvExit;
            }
            goto TwEvExit;
        }
    }
    else {
        /* Slave mode */
        I2C_DIS_BUF(I2Cx);
        I2C_DIS_EVT(I2Cx);
        DBGP2(1);
    }

TwEvExit:
   DBGP2(0);
   DBGP1(0);
}