static inline void *coherent_kvaddr(struct page *page, unsigned long base, unsigned long vaddr, unsigned long *paddr) { if (PageHighMem(page) || !DCACHE_ALIAS_EQ(page_to_phys(page), vaddr)) { *paddr = page_to_phys(page); return (void *)(base + (vaddr & DCACHE_ALIAS_MASK)); } else { *paddr = 0; return page_to_virt(page); } }
static inline void kmap_invalidate_coherent(struct page *page, unsigned long vaddr) { if (!DCACHE_ALIAS_EQ(page_to_phys(page), vaddr)) { unsigned long kvaddr; if (!PageHighMem(page)) { kvaddr = (unsigned long)page_to_virt(page); __invalidate_dcache_page(kvaddr); } else { kvaddr = TLBTEMP_BASE_1 + (page_to_phys(page) & DCACHE_ALIAS_MASK); __invalidate_dcache_page_alias(kvaddr, page_to_phys(page)); } } }
int __init mem_module_init(void) { UINT phys, virt; printk("-----------------\n"); printk("PAGE_OFFSET = %x\n", (UINT)PAGE_OFFSET); printk("This module addr: %x(%u MB)\n", (UINT)&virt, MB(&virt)); phys = virt_to_phys((void*)&virt); printk("phys: %x(%u MB)\n", phys, MB(phys)); /*申请的内存位于物理内存映射区域,与真实物理地址只有一个固定偏移*/ free_pg = (void*)__get_free_page(0); virt = (UINT)free_pg; printk("->Free page mem: %x(%u MB)\n", virt, MB(virt)); phys = virt_to_phys(free_pg); printk("phys: %x(%u MB)\n", phys, MB(phys)); alloc_pg = alloc_page(GFP_KERNEL); virt = page_to_virt(alloc_pg); printk("->Alloc page mem: %x(%u MB)\n", virt, MB(virt)); phys = virt_to_phys(alloc_pg); printk("phys: %x(%u MB)\n", phys, MB(phys)); /*申请的内存位于物理内存映射区域,与真实物理地址只有一个固定偏移*/ kmallocmem = (void*)kmalloc(100, 0); virt = (UINT)kmallocmem; printk("->Kmalloc mem: %x(%u MB)\n", virt, MB(virt)); phys = virt_to_phys(kmallocmem); printk("phys: %x(%u MB)\n", phys, MB(phys)); /*申请的内存位于vmalloc_start~vmalloc_end之间,与物理地址没有简短的转换关系*/ vmallocmem = (void*)vmalloc(100000); virt = (UINT)vmallocmem; printk("->Vmalloc mem: %x(%u MB)\n", virt, MB(virt)); phys = virt_to_phys(vmallocmem); printk("phys: %x(%u MB)\n", phys, MB(phys)); printk("-----------------\n"); return 0; }
static int trans_open(struct inode *i, struct file *f) { struct trans_channel *c; struct page *p; printl("trans_open\n"); c = kmalloc(sizeof(struct trans_channel), GFP_KERNEL); if (!c) return -ENOMEM; trans_channel_init(c); p = alloc_pages(GFP_KERNEL, TRANS_PAGE_ORDER); if (!p) goto free; c->mem = page_to_virt(p); f->private_data = c; return 0; free: kfree(c); return -ENOMEM; }
static void * xencomm_vaddr(unsigned long paddr, struct page_info *page) { return (void*)((paddr & ~PAGE_MASK) | (unsigned long)page_to_virt(page)); }
static int kvmppc_xive_native_set_queue_config(struct kvmppc_xive *xive, long eq_idx, u64 addr) { struct kvm *kvm = xive->kvm; struct kvm_vcpu *vcpu; struct kvmppc_xive_vcpu *xc; void __user *ubufp = (void __user *) addr; u32 server; u8 priority; struct kvm_ppc_xive_eq kvm_eq; int rc; __be32 *qaddr = 0; struct page *page; struct xive_q *q; gfn_t gfn; unsigned long page_size; /* * Demangle priority/server tuple from the EQ identifier */ priority = (eq_idx & KVM_XIVE_EQ_PRIORITY_MASK) >> KVM_XIVE_EQ_PRIORITY_SHIFT; server = (eq_idx & KVM_XIVE_EQ_SERVER_MASK) >> KVM_XIVE_EQ_SERVER_SHIFT; if (copy_from_user(&kvm_eq, ubufp, sizeof(kvm_eq))) return -EFAULT; vcpu = kvmppc_xive_find_server(kvm, server); if (!vcpu) { pr_err("Can't find server %d\n", server); return -ENOENT; } xc = vcpu->arch.xive_vcpu; if (priority != xive_prio_from_guest(priority)) { pr_err("Trying to restore invalid queue %d for VCPU %d\n", priority, server); return -EINVAL; } q = &xc->queues[priority]; pr_devel("%s VCPU %d priority %d fl:%x shift:%d addr:%llx g:%d idx:%d\n", __func__, server, priority, kvm_eq.flags, kvm_eq.qshift, kvm_eq.qaddr, kvm_eq.qtoggle, kvm_eq.qindex); /* * sPAPR specifies a "Unconditional Notify (n) flag" for the * H_INT_SET_QUEUE_CONFIG hcall which forces notification * without using the coalescing mechanisms provided by the * XIVE END ESBs. This is required on KVM as notification * using the END ESBs is not supported. */ if (kvm_eq.flags != KVM_XIVE_EQ_ALWAYS_NOTIFY) { pr_err("invalid flags %d\n", kvm_eq.flags); return -EINVAL; } rc = xive_native_validate_queue_size(kvm_eq.qshift); if (rc) { pr_err("invalid queue size %d\n", kvm_eq.qshift); return rc; } /* reset queue and disable queueing */ if (!kvm_eq.qshift) { q->guest_qaddr = 0; q->guest_qshift = 0; rc = xive_native_configure_queue(xc->vp_id, q, priority, NULL, 0, true); if (rc) { pr_err("Failed to reset queue %d for VCPU %d: %d\n", priority, xc->server_num, rc); return rc; } if (q->qpage) { put_page(virt_to_page(q->qpage)); q->qpage = NULL; } return 0; } if (kvm_eq.qaddr & ((1ull << kvm_eq.qshift) - 1)) { pr_err("queue page is not aligned %llx/%llx\n", kvm_eq.qaddr, 1ull << kvm_eq.qshift); return -EINVAL; } gfn = gpa_to_gfn(kvm_eq.qaddr); page = gfn_to_page(kvm, gfn); if (is_error_page(page)) { pr_err("Couldn't get queue page %llx!\n", kvm_eq.qaddr); return -EINVAL; } page_size = kvm_host_page_size(kvm, gfn); if (1ull << kvm_eq.qshift > page_size) { pr_warn("Incompatible host page size %lx!\n", page_size); return -EINVAL; } qaddr = page_to_virt(page) + (kvm_eq.qaddr & ~PAGE_MASK); /* * Backup the queue page guest address to the mark EQ page * dirty for migration. */ q->guest_qaddr = kvm_eq.qaddr; q->guest_qshift = kvm_eq.qshift; /* * Unconditional Notification is forced by default at the * OPAL level because the use of END ESBs is not supported by * Linux. */ rc = xive_native_configure_queue(xc->vp_id, q, priority, (__be32 *) qaddr, kvm_eq.qshift, true); if (rc) { pr_err("Failed to configure queue %d for VCPU %d: %d\n", priority, xc->server_num, rc); put_page(page); return rc; } /* * Only restore the queue state when needed. When doing the * H_INT_SET_SOURCE_CONFIG hcall, it should not. */ if (kvm_eq.qtoggle != 1 || kvm_eq.qindex != 0) { rc = xive_native_set_queue_state(xc->vp_id, priority, kvm_eq.qtoggle, kvm_eq.qindex); if (rc) goto error; } rc = kvmppc_xive_attach_escalation(vcpu, priority, xive->single_escalation); error: if (rc) kvmppc_xive_native_cleanup_queue(vcpu, priority); return rc; }
static void run_tool(uint8_t devices) { uint8_t highlighted; for (uint8_t i = 0; i < 4; i++) { if (ide_device_is_present(i) && ide_device_get_type(i) == 0) { highlighted = i; break; } } bool selected[4] = {0,0,0,0}; bool selecting = true; uint8_t selectedNum = 0; while (selecting) { console_clear(); print_header(); console_puts("Please select the drives which you would like to erase.\n"); for (uint8_t i = 0; i < 4; i++) { if (ide_device_is_present(i) && ide_device_get_type(i) == 0) { uint8_t foreground = 0x7, background = 0x0; if (selected[i]) foreground = 0xC; if (highlighted == i) { background = 0xF; if (foreground == 0x7) foreground = 0x0; } console_color((background << 4) + foreground); console_putsf(" - ATA Device %u (%s) %7uMB - %s\n", i, ide_device_is_dma_capable(i) ? "DMA" : "PIO", ide_device_get_size(i) / 1024 / 2, ide_device_get_string(i, IDE_STRING_MODEL)); console_color(0x07); } } for (int i = 0; i < 10 - devices; i++) console_puts("\n"); console_puts("Use the \"ARROW KEYS\" to highlight a drive.\n"); console_puts("Press \"SPACE\" to select/deselect the currently highlighted drive.\n\n"); console_puts("NOTE: You must select at least one drive to continue.\n\n"); console_puts("Press \"ENTER\" to continue.\n"); console_puts("Press \"ESCAPE\" to go back."); switch (get_key()) { case '\n': if (selectedNum > 0) { selecting = false; } break; case '\1': return; case '\3': do { highlighted--; if (highlighted > 3) highlighted = 3; } while (!(ide_device_is_present(highlighted) && ide_device_get_type(highlighted) == 0)); break; case '\5': do { highlighted++; if (highlighted == 4) highlighted = 0; } while (!(ide_device_is_present(highlighted) && ide_device_get_type(highlighted) == 0)); break; case ' ': selected[highlighted] = !selected[highlighted]; selectedNum += selected[highlighted] ? 1 : -1; break; } } console_clear(); print_header(); console_puts("Please select the drives which you would like to erase.\n"); for (uint8_t i = 0; i < 4; i++) { if (ide_device_is_present(i) && ide_device_get_type(i) == 0) { uint8_t foreground = 0x7, background = 0x0; if (selected[i]) foreground = 0xC; console_color((background << 4) + foreground); console_putsf(" - ATA Device %u (%s) %7uMB - %s\n", i, ide_device_is_dma_capable(i) ? "DMA" : "PIO", ide_device_get_size(i) / 1024 / 2, ide_device_get_string(i, IDE_STRING_MODEL)); console_color(0x07); } } console_puts("\n\nPlease enter the number of passes to be performed (max 99, 0 to cancel): "); uint8_t idx = 0; char raw_passes[3]; char c; do { c = get_key(); if (c == '\x7f' && idx > 0) { idx--; console_cursor(console_row(), console_col() - 1); console_puts(" "); console_cursor(console_row(), console_col() - 1); } else if (c >= '0' && c <= '9' && idx < 2) { console_putsf("%c", c); raw_passes[idx] = c; idx++; } } while (!(c == '\n' && idx != 0)); raw_passes[idx] = '\0'; uint32_t passes = atoi(raw_passes); if (passes == 0) return; console_puts("\n\nPress \"ENTER\" to "); console_color(0x0C); console_puts("WIPE THE ATA DISKS SELECTED ABOVE"); console_color(0x07); console_putsf(" in %u pass", passes); if (passes != 1) console_puts("es"); console_puts(".\nPress \"ESCAPE\" to cancel and go back.\n\n"); bool wait = true; while (wait) { switch (get_key()) { case '\1': return; break; case '\n': wait = false; } } console_clear(); console_puts("Starting Data Erasure Tool...\n\n"); uint8_t *space = (uint8_t *) page_to_virt(alloc_page(0)); for (uint32_t i = 1; i < 64; i++) { alloc_page(0); console_putsf("Initializing... %3u%%\r", ((i + 1) * 100) / 64); } console_puts("Initializing... 100%%\n"); uint8_t bit = 0x00; for (uint32_t pass = 0; pass < passes; pass++) { console_clear(); console_puts("Starting Data Erasure Tool...\n\n"); console_putsf("Initializing... 100%%\n", space); console_putsf("\nWriting Pass %02u of %02u...\n", pass + 1, passes); for (uint32_t i = 0; i < (64 * 4 * 1024); i++) { space[i] = bit; } int device = 0; for (uint32_t i = 0; i < 4; i++) { if (selected[i]) { device++; uint32_t count = 0; uint32_t written = 0; while(written < ide_device_get_size(i)) { count++; console_putsf(" - Writing to device %u... %3u%% %c\r", device, (written * 100) / ide_device_get_size(i), twirls[(count / 10) % 4]); written += ide_write_sectors_same(i, ide_device_get_size(i) - written, written, space) / 512; } console_putsf(" - Writing to device %u... 100%% \n", device); } } bit = ~bit; } console_color(0x0A); console_puts("\nOperation completed successfully! "); console_color(0x07); console_puts("You may now turn the computer off."); beep(); die(); }