/* Returns: mfn for the given (hvm guest) vaddr */ static unsigned long dbg_hvm_va2mfn(dbgva_t vaddr, struct domain *dp, int toaddr, unsigned long *gfn) { unsigned long mfn; uint32_t pfec = PFEC_page_present; p2m_type_t gfntype; DBGP2("vaddr:%lx domid:%d\n", vaddr, dp->domain_id); *gfn = paging_gva_to_gfn(dp->vcpu[0], vaddr, &pfec); if ( *gfn == INVALID_GFN ) { DBGP2("kdb:bad gfn from gva_to_gfn\n"); return INVALID_MFN; } mfn = mfn_x(get_gfn(dp, *gfn, &gfntype)); if ( p2m_is_readonly(gfntype) && toaddr ) { DBGP2("kdb:p2m_is_readonly: gfntype:%x\n", gfntype); return INVALID_MFN; } DBGP2("X: vaddr:%lx domid:%d mfn:%lx\n", vaddr, dp->domain_id, mfn); return mfn; }
/* Returns: mfn for the given (hvm guest) vaddr */ static mfn_t dbg_hvm_va2mfn(dbgva_t vaddr, struct domain *dp, int toaddr, gfn_t *gfn) { mfn_t mfn; uint32_t pfec = PFEC_page_present; p2m_type_t gfntype; DBGP2("vaddr:%lx domid:%d\n", vaddr, dp->domain_id); *gfn = _gfn(paging_gva_to_gfn(dp->vcpu[0], vaddr, &pfec)); if ( gfn_eq(*gfn, INVALID_GFN) ) { DBGP2("kdb:bad gfn from gva_to_gfn\n"); return INVALID_MFN; } mfn = get_gfn(dp, gfn_x(*gfn), &gfntype); if ( p2m_is_readonly(gfntype) && toaddr ) { DBGP2("kdb:p2m_is_readonly: gfntype:%x\n", gfntype); mfn = INVALID_MFN; } else DBGP2("X: vaddr:%lx domid:%d mfn:%#"PRI_mfn"\n", vaddr, dp->domain_id, mfn_x(mfn)); if ( mfn_eq(mfn, INVALID_MFN) ) { put_gfn(dp, gfn_x(*gfn)); *gfn = INVALID_GFN; } return mfn; }
/* * 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; }
/* Returns: mfn for the given (pv guest) vaddr */ static unsigned long dbg_pv_va2mfn(dbgva_t vaddr, struct domain *dp, uint64_t pgd3val) { 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 ) { l3t = map_domain_page(mfn); l3t += (cr3 & 0xFE0UL) >> 3; l3e = l3t[l3_table_offset(vaddr)]; mfn = l3e_get_pfn(l3e); unmap_domain_page(l3t); if ( !(l3e_get_flags(l3e) & _PAGE_PRESENT) ) return INVALID_MFN; }
/* * 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); }