static void test_vm_unmap(void) { paddr_t paddr; vaddr_t vaddr; vm_as_t* as; as = vm_get_kernel_as(); serial_printl("[?] test unmap\n"); vaddr = (vaddr_t)0xb0000000; paddr = phys_alloc(); vm_map(as, vaddr, paddr); /* no page fault */ *(uint32_t*)vaddr = 0x2a; vm_unmap(as, vaddr); phys_free(paddr); /* page fault */ *(uint32_t*)vaddr = 0x2a; }
static void test_vm_map(void) { paddr_t paddr; vaddr_t vaddr; vm_as_t* as; as = vm_get_kernel_as(); vaddr = (vaddr_t)0xb0000000; paddr = phys_alloc(); vm_map(as, vaddr + PHYS_FRAME_SIZE * 0, paddr); *(volatile uint32_t*)(vaddr + PHYS_FRAME_SIZE * 0) = 0x2a; serial_printl("[?] --> %x\n", *(volatile uint32_t*)(vaddr + PHYS_FRAME_SIZE * 0)); vm_map(as, vaddr + PHYS_FRAME_SIZE * 1, paddr); *(volatile uint32_t*)(vaddr + PHYS_FRAME_SIZE * 1) = 0x2a; serial_printl("[?] --> %x\n", *(volatile uint32_t*)(vaddr + PHYS_FRAME_SIZE * 1)); vm_map(as, vaddr + PHYS_FRAME_SIZE * 2, paddr); *(volatile uint32_t*)(vaddr + PHYS_FRAME_SIZE * 2) = 0x2a; serial_printl("[?] --> %x\n", *(volatile uint32_t*)(vaddr + PHYS_FRAME_SIZE * 2)); phys_free(paddr); }
/* alloc a block */ void * mm_alloc(size_t size) { unsigned bnum = (unsigned) ((size + 1) / (PHYS_PAGE_SIZE * 1024)) + 1; // / PHYS_PAGE_SIZE + 1; return (void *)phys_alloc(bnum); }
void phys_test(void) { paddr_t a; paddr_t b; paddr_t c; serial_printl("[?] test\n"); phys_debug(); a = phys_alloc(); serial_printl("%x\n", (uint32_t)a); phys_free(a); a = phys_alloc(); serial_printl("%x\n", (uint32_t)a); phys_free(a); phys_debug(); a = phys_alloc(); serial_printl("%x\n", (uint32_t)a); b = phys_alloc(); serial_printl("%x\n", (uint32_t)b); c = phys_alloc(); serial_printl("%x\n", (uint32_t)c); phys_debug(); phys_free(a); phys_free(b); phys_free(c); phys_debug(); b = phys_alloc_range(101); serial_printl("b == %x\n", (uint32_t)b); phys_free_range(b, 101); phys_debug(); phys_debug(); }
static void test_page_fault(void) { volatile uint32_t* vaddr_0 = (uint32_t*)0xb0000000; volatile uint32_t* vaddr_1 = (uint32_t*)0xb0001000; volatile uint32_t* vaddr_2 = (uint32_t*)0xb0002000; paddr_t paddr = phys_alloc(); vm_as_t* as; as = vm_get_kernel_as(); vm_map(as, (vaddr_t)vaddr_0, paddr); vm_map(as, (vaddr_t)vaddr_1, paddr); vm_map(as, (vaddr_t)vaddr_2, paddr); *vaddr_0 = 0x2a; if ((*vaddr_0 != 0x2a) || (*vaddr_0 != *vaddr_1) || (*vaddr_0 != *vaddr_2)) BUG(); }
/** Register a new PCI ATA channel. * @param pci_device PCI device the channel is on. * @param idx Channel index. * @param ctrl_base Control registers base address. * @param cmd_base Command registers base address. * @param bm_base Bus master base address. * @param irq IRQ number. * @return Pointer to ATA channel structure if present. */ static ata_channel_t *pci_ata_channel_add(pci_device_t *pci_device, int idx, uint32_t ctrl_base, uint32_t cmd_base, uint32_t bm_base, uint32_t irq) { uint16_t pci_cmd_old, pci_cmd_new; pci_ata_channel_t *channel; bool dma = true; status_t ret; /* Configure the PCI device appropriately. */ pci_cmd_old = pci_cmd_new = pci_config_read16(pci_device, PCI_CONFIG_COMMAND); pci_cmd_new &= ~PCI_COMMAND_INT_DISABLE; pci_cmd_new |= (PCI_COMMAND_IO | PCI_COMMAND_BUS_MASTER); if(pci_cmd_new != pci_cmd_old) { pci_config_write16(pci_device, PCI_CONFIG_COMMAND, pci_cmd_new); kprintf(LOG_DEBUG, "ata: reconfigured PCI device %d:%02x.%d (old: 0x%04x, new: 0x%04x)\n", pci_device->bus, pci_device->device, pci_device->function, pci_cmd_old, pci_cmd_new); } /* Check presence by writing a value to the low LBA port on the channel, * then reading it back. If the value is the same, it is present. */ out8(cmd_base + ATA_CMD_REG_LBA_LOW, 0xAB); if(in8(cmd_base + ATA_CMD_REG_LBA_LOW) != 0xAB) { if(pci_cmd_new != pci_cmd_old) { pci_config_write16(pci_device, PCI_CONFIG_COMMAND, pci_cmd_old); } return NULL; } /* Allocate our information structure. */ channel = kmalloc(sizeof(*channel), MM_WAIT); channel->channel = NULL; channel->pci_device = pci_device; channel->ctrl_base = ctrl_base; channel->cmd_base = cmd_base; channel->bus_master_base = bm_base + (idx * 8); channel->irq = irq; channel->prdt = NULL; /* If the bus master is in simplex mode, disable DMA on the second * channel. According to the Haiku code, Intel controllers use this for * something other than simplex mode. */ if(pci_device->vendor_id != 0x8086) { if(in8(bm_base + PCI_ATA_BM_REG_STATUS) & PCI_ATA_BM_STATUS_SIMPLEX && idx > 1) { dma = false; } } /* Allocate a PRDT if necessary. */ if(dma) { phys_alloc(PRDT_SIZE, 0, 0, 0, (phys_ptr_t)0x100000000, MM_WAIT, &channel->prdt_phys); channel->prdt = phys_map(channel->prdt_phys, PRDT_SIZE, MM_WAIT); } /* Register the IRQ handler. */ ret = irq_register(channel->irq, pci_ata_irq_handler, NULL, channel); if(ret != STATUS_SUCCESS) { kprintf(LOG_WARN, "ata: failed to register PCI ATA IRQ handler %u\n", channel->irq); if(dma) { phys_unmap(channel->prdt, PRDT_SIZE, true); phys_free(channel->prdt_phys, PRDT_SIZE); } kfree(channel); return NULL; } /* Try to register the ATA channel. */ channel->channel = ata_sff_channel_add(pci_device->node, idx, &pci_ata_channel_ops, channel, dma, PRDT_ENTRIES, (phys_ptr_t)0x100000000); if(!channel->channel) { irq_unregister(channel->irq, pci_ata_irq_handler, NULL, channel); if(dma) { phys_unmap(channel->prdt, PRDT_SIZE, true); phys_free(channel->prdt_phys, PRDT_SIZE); } kfree(channel); return NULL; } return channel->channel; }