From e362b56b4fd73db86eb8bf62baa8963eec0a967b Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Fri, 17 Jan 2020 19:59:20 +0100 Subject: Kernel: Move kernel above the 3GB virtual address mark The kernel and its static data structures are no longer identity-mapped in the bottom 8MB of the address space, but instead move above 3GB. The first 8MB above 3GB are pseudo-identity-mapped to the bottom 8MB of the physical address space. But things don't have to stay this way! Thanks to Jesse who made an earlier attempt at this, it was really easy to get device drivers working once the page tables were in place! :^) Fixes #734. --- Kernel/Devices/PATAChannel.cpp | 24 +++++++++++++----------- Kernel/Devices/PATAChannel.h | 3 ++- 2 files changed, 15 insertions(+), 12 deletions(-) (limited to 'Kernel/Devices') diff --git a/Kernel/Devices/PATAChannel.cpp b/Kernel/Devices/PATAChannel.cpp index 6866139e06..6da8abecda 100644 --- a/Kernel/Devices/PATAChannel.cpp +++ b/Kernel/Devices/PATAChannel.cpp @@ -102,6 +102,8 @@ PATAChannel::PATAChannel(ChannelType type, bool force_pio) m_dma_enabled.resource() = true; ProcFS::add_sys_bool("ide_dma", m_dma_enabled); + m_prdt_page = MM.allocate_supervisor_physical_page(); + initialize(force_pio); detect_disks(); } @@ -131,7 +133,7 @@ void PATAChannel::initialize(bool force_pio) // Let's try to set up DMA transfers. PCI::enable_bus_mastering(m_pci_address); - m_prdt.end_of_table = 0x8000; + prdt().end_of_table = 0x8000; m_bus_master_base = PCI::get_BAR4(m_pci_address) & 0xfffc; m_dma_buffer_page = MM.allocate_supervisor_physical_page(); kprintf("PATAChannel: Bus master IDE: I/O @ %x\n", m_bus_master_base); @@ -253,16 +255,16 @@ bool PATAChannel::ata_read_sectors_with_dma(u32 lba, u16 count, u8* outbuf, bool current->pid(), lba, count, outbuf); #endif - m_prdt.offset = m_dma_buffer_page->paddr(); - m_prdt.size = 512 * count; + prdt().offset = m_dma_buffer_page->paddr(); + prdt().size = 512 * count; - ASSERT(m_prdt.size <= PAGE_SIZE); + ASSERT(prdt().size <= PAGE_SIZE); // Stop bus master IO::out8(m_bus_master_base, 0); // Write the PRDT location - IO::out32(m_bus_master_base + 4, (u32)&m_prdt); + IO::out32(m_bus_master_base + 4, m_prdt_page->paddr().get()); // Turn on "Interrupt" and "Error" flag. The error flag should be cleared by hardware. IO::out8(m_bus_master_base + 2, IO::in8(m_bus_master_base + 2) | 0x6); @@ -310,7 +312,7 @@ bool PATAChannel::ata_read_sectors_with_dma(u32 lba, u16 count, u8* outbuf, bool if (m_device_error) return false; - memcpy(outbuf, m_dma_buffer_page->paddr().as_ptr(), 512 * count); + memcpy(outbuf, m_dma_buffer_page->paddr().offset(0xc0000000).as_ptr(), 512 * count); // I read somewhere that this may trigger a cache flush so let's do it. IO::out8(m_bus_master_base + 2, IO::in8(m_bus_master_base + 2) | 0x6); @@ -326,18 +328,18 @@ bool PATAChannel::ata_write_sectors_with_dma(u32 lba, u16 count, const u8* inbuf current->pid(), lba, count, inbuf); #endif - m_prdt.offset = m_dma_buffer_page->paddr(); - m_prdt.size = 512 * count; + prdt().offset = m_dma_buffer_page->paddr(); + prdt().size = 512 * count; - memcpy(m_dma_buffer_page->paddr().as_ptr(), inbuf, 512 * count); + memcpy(m_dma_buffer_page->paddr().offset(0xc0000000).as_ptr(), inbuf, 512 * count); - ASSERT(m_prdt.size <= PAGE_SIZE); + ASSERT(prdt().size <= PAGE_SIZE); // Stop bus master IO::out8(m_bus_master_base, 0); // Write the PRDT location - IO::out32(m_bus_master_base + 4, (u32)&m_prdt); + IO::out32(m_bus_master_base + 4, m_prdt_page->paddr().get()); // Turn on "Interrupt" and "Error" flag. The error flag should be cleared by hardware. IO::out8(m_bus_master_base + 2, IO::in8(m_bus_master_base + 2) | 0x6); diff --git a/Kernel/Devices/PATAChannel.h b/Kernel/Devices/PATAChannel.h index 6db5953b44..19d4c94e8e 100644 --- a/Kernel/Devices/PATAChannel.h +++ b/Kernel/Devices/PATAChannel.h @@ -65,7 +65,8 @@ private: WaitQueue m_irq_queue; PCI::Address m_pci_address; - PhysicalRegionDescriptor m_prdt; + PhysicalRegionDescriptor& prdt() { return *reinterpret_cast(m_prdt_page->paddr().offset(0xc0000000).as_ptr()); } + RefPtr m_prdt_page; RefPtr m_dma_buffer_page; u16 m_bus_master_base { 0 }; Lockable m_dma_enabled; -- cgit v1.2.3