#include <vmalloc.h>
void* ioremap(paddr_t paddr, size_t size);
-void iounmap(void* vaddr);
+void iounmap(vaddr_t vaddr);
dev_t root_dev;
- vaddr_t hpet_base;
-
// 按理这些信息应该按CPU存储,简化实现
lapic_t* lapic;
paddr_t lapic_addr;
struct vm_struct* vm_next;
} vm_struct_t;
-vm_struct_t* get_vm_area(size_t size, uint32_t flags);
+vm_struct_t* alloc_vm_area(size_t size, uint32_t flags);
vm_struct_t* find_vm_area(vaddr_t vaddr);
void free_vm_area(vm_struct_t* vm);
void hpet0_irq_handler(unsigned int irq, pt_regs_t* regs, void* dev_id) {
hpet_ticks++;
- vaddr_t hpet_base = system.hpet_base;
- assert(hpet_base != 0);
-
uint8_t* p = (uint8_t*)0xC00B8002;
*p = *p == ' ' ? 'E' : ' ';
add_irq_bh_handler(hpet0_bh_handler, NULL);
- // uint64_t main_cnt = *(volatile uint64_t*)(hpet_base + 0xF0);
- // uint64_t counter = *(volatile uint64_t*)(hpet_base + 0x108);
- // printk("main_cnt: %lu counter: %lu abc\n", main_cnt, counter);
-
system.lapic->write(LAPIC_EOI, 0);
}
printk("RCBA: %08x %08x\n", RCBA, rcba_phys_base);
// 把RCBA物理基地址映射到内核空间
- vaddr_t rcba_virt_base = (vaddr_t)ioremap(rcba_phys_base, 4 * PAGE_SIZE);
- // set_fixmap(FIX_RCBA_BASE, rcba_phys_base);
- // uint32_t rcba_virt_base = fixid_to_vaddr(FIX_RCBA_BASE);
+ uint32_t rcba_page_offset = 3 * PAGE_SIZE;
+ vaddr_t rcba_virt_base = (vaddr_t)ioremap(rcba_phys_base, 4 * PAGE_SIZE - rcba_page_offset);
printk("RCBA base %08x mapped to %08x\n", rcba_phys_base, rcba_virt_base);
// OIC
// bit[15:10]: 保留
//
// 上面得搞成ioremap映射, 因为0x31FE这个超过一页也就是4K了。
- uint16_t* pOIC = (uint16_t*)((uint8_t*)rcba_virt_base + 0x31FE);
+ uint16_t* pOIC = (uint16_t*)((uint8_t*)rcba_virt_base + 0x31FE - rcba_page_offset);
printk("OIC: %04x\n", *pOIC);
*pOIC = *pOIC | (1 << 8);
printk("OIC: %04x\n", *pOIC);
- // TODO
- // iounmap(rcba_virt_base);
+
+ iounmap(rcba_virt_base);
uint64_t dst_cpuid = 0;
irq_set_chip(0x00, &ioapic_chip);
irq_set_chip(0x01, &ioapic_chip);
#endif
+
+ rcba_phys_base = RCBA & (~0x3FFF);
+ printk("RCBA: %08x %08x\n", RCBA, rcba_phys_base);
+ rcba_virt_base = (vaddr_t)ioremap(rcba_phys_base, 4 * PAGE_SIZE - rcba_page_offset);
+ printk("RCBA base %08x mapped to %08x\n", rcba_phys_base, rcba_virt_base);
// HPTC: High Precision Timer Control Register
// bit[1:0] 地址映射范围选择域
// 取值 地址映射范围
*pHPTC = *pHPTC | (1 << 7) | (0x00);
io_mfence();
printk("HPTC: %08x\n", *pHPTC);
+ iounmap(rcba_virt_base);
vaddr_t hpet_base = (vaddr_t)ioremap(0xFED00000, 0x3FF);
- system.hpet_base = hpet_base;
printk("HPET base %08x mapped to %08x\n", 0xFED00000, hpet_base);
uint64_t GEN_CONF = *(volatile uint64_t*)(hpet_base + 0x10);
printk("TIM0_CONF: 0x%08x%08x\n", (uint32_t)(TIM0_CONF >> 32), (uint32_t)TIM0_CONF);
uint64_t x = freq_mhz * 1000000ULL;
+ x >>= 1;
*(volatile uint32_t*)(hpet_base + 0x108 + 0x04) = (uint32_t)(x >> 32);
*(volatile uint32_t*)(hpet_base + 0x108 + 0x00) = (uint32_t)(x & 0xFFFFFFFF);
// *(volatile uint64_t*)(hpet_base + 0x108) = x;
}
}
+void ioremap_page_range_clear(vaddr_t vaddr, size_t size) {
+ assert(PAGE_DOWN(size) == size);
+
+ for (int i = 0; i < size / PAGE_SIZE; i++) {
+ page_map(vaddr + i * PAGE_SIZE, 0, 0);
+ }
+}
+
void* ioremap(paddr_t phys_addr, size_t size) {
size = PAGE_UP(size);
- vm_struct_t* vm_area = get_vm_area(size, VM_IOREMAP);
+ vm_struct_t* vm_area = alloc_vm_area(size, VM_IOREMAP);
if (!vm_area) {
return NULL;
}
return (void*)vm_area->vm_vaddr;
}
-void iounmap(void* addr) {
- // vm_struct_t* vm_area = find_vm_area((vaddr_t)addr);
- // if (!vm_area) {
- // return;
- // }
+void iounmap(vaddr_t vaddr) {
+ vm_struct_t* vm_area = find_vm_area(vaddr);
+ assert(vm_area != NULL);
+ assert(vm_area->vm_flags & VM_IOREMAP);
+
+ printk("iounmap: 0x%08x size %u\n", vm_area->vm_vaddr, vm_area->vm_size);
- // if (!(vm_area->vm_flags & VM_IOREMAP)) {
- // return;
- // }
+ free_vm_area(vm_area);
- // free_vm_area(vm_area);
+ ioremap_page_range_clear(vm_area->vm_vaddr, vm_area->vm_size);
}
#include <irq.h>
#include <page.h>
#include <assert.h>
+#include <string.h>
static vm_struct_t* vm_area_list = NULL;
vaddr_t vm_vaddr_base = VMALLOC_VADDR_BASE + (8 * 1024 * 1024);
vaddr_t vm_vaddr_end = VMALLOC_VADDR_END;
-vm_struct_t* get_vm_area(size_t size, uint32_t flags) {
+vm_struct_t* alloc_vm_area(size_t size, uint32_t flags) {
// assert size是页对齐
assert(PAGE_DOWN(size) == size);
assert(vm_vaddr_base < vm_vaddr_end);
assert(vaddr < vm_vaddr_end);
assert(vm_area_list != NULL);
+ uint32_t eflags;
+ irq_save(eflags);
+
vm_struct_t* curt = vm_area_list;
while (curt != NULL) {
assert(curt->vm_vaddr + curt->vm_size <= vm_vaddr_end);
if (vaddr == curt->vm_vaddr) {
+ irq_restore(eflags);
return curt;
}
curt = curt->vm_next;
}
+ irq_restore(eflags);
+
return NULL;
}
void free_vm_area(vm_struct_t* vm_area) {
assert(vm_area != NULL);
assert(vm_area->vm_size != 0);
+ assert(vm_area->vm_size % PAGE_SIZE == 0);
+ assert(vm_area->vm_size >= (2 * PAGE_SIZE));
assert(vm_area->vm_vaddr >= vm_vaddr_base);
assert(vm_area->vm_vaddr + vm_area->vm_size <= vm_vaddr_end);
assert(vm_area_list != NULL);
// TODO
+
+ uint32_t eflags;
+ irq_save(eflags);
+
+ vm_struct_t* prev = NULL;
+ vm_struct_t* curt = vm_area_list;
+
+ while (curt != NULL) {
+ if (curt == vm_area) {
+ if (prev == NULL) {
+ // 只有链表上仅有一个节点,且这个节点就是要删除的节点的情况下prev才可能为NULL
+ assert(vm_area_list == vm_area);
+ assert(vm_area->vm_next == NULL);
+
+ //
+ vm_area_list = curt->vm_next;
+ } else {
+ prev->vm_next = curt->vm_next;
+ }
+
+ // 释放前先清空vm_struct避免连续二次释放
+ memset(curt, 0, sizeof(vm_struct_t));
+
+ kfree(curt);
+
+ irq_restore(eflags);
+ return;
+ }
+
+ prev = curt;
+ curt = curt->vm_next;
+ }
+
+ // 不应该出现这种情况
+ assert(0 && "vm_area not found");
+ irq_restore(eflags);
}
void* vmalloc(size_t size) {