📄 extmem.c
字号:
break; } } if (seg == NULL) { /* find out the attributes of this shared segment */ dcss_diag_query(dcss_name, &rwattr, &shattr, &segstart, &segend); /* does segment collide with main memory? */ for (i=0; i < MEMORY_CHUNKS; i++) { if (memory_chunk[i].type != 0) continue; if (memory_chunk[i].addr > segend) continue; if (memory_chunk[i].addr + memory_chunk[i].size <= segstart) continue; spin_unlock(&dcss_lock); return -ENOENT; } /* or does it collide with other (loaded) segments? */ list_for_each(l, &dcss_list) { tmp = list_entry(l, struct dcss_segment, list); if ((segstart <= tmp->end && segstart >= tmp->start_addr) || (segend <= tmp->end && segend >= tmp->start_addr) || (segstart <= tmp->start_addr && segend >= tmp->end)) { PRINT_ERR("Segment Overlap!\n"); spin_unlock(&dcss_lock); return -ENOENT; } } /* do case statement on segtype */ /* if asking for shared ro, shared rw works */ /* if asking for exclusive ro, exclusive rw works */ switch(segtype) { case SEGMENT_SHARED_RO: if (shattr > 1 || rwattr > 1) { spin_unlock(&dcss_lock); return -ENOENT; } else { if (shattr == 0 && rwattr == 0) rc = SEGMENT_EXCLUSIVE_RO; if (shattr == 0 && rwattr == 1) rc = SEGMENT_EXCLUSIVE_RW; if (shattr == 1 && rwattr == 0) rc = SEGMENT_SHARED_RO; if (shattr == 1 && rwattr == 1) rc = SEGMENT_SHARED_RW; } break; case SEGMENT_SHARED_RW: if (shattr > 1 || rwattr != 1) { spin_unlock(&dcss_lock); return -ENOENT; } else { if (shattr == 0) rc = SEGMENT_EXCLUSIVE_RW; if (shattr == 1) rc = SEGMENT_SHARED_RW; } break; case SEGMENT_EXCLUSIVE_RO: if (shattr > 0 || rwattr > 1) { spin_unlock(&dcss_lock); return -ENOENT; } else { if (rwattr == 0) rc = SEGMENT_EXCLUSIVE_RO; if (rwattr == 1) rc = SEGMENT_EXCLUSIVE_RW; } break; case SEGMENT_EXCLUSIVE_RW:/* if (shattr != 0 || rwattr != 1) { spin_unlock(&dcss_lock); return -ENOENT; } else {*/ rc = SEGMENT_EXCLUSIVE_RW;// } break; default: spin_unlock(&dcss_lock); return -ENOENT; } /* end switch */ seg = kmalloc(sizeof(struct dcss_segment), GFP_DMA); if (seg != NULL) { memcpy(seg->dcss_name, dcss_name, 8); if (rc == SEGMENT_EXCLUSIVE_RW) { if (dcss_diag(DCSS_LOADNSR, seg->dcss_name, &seg->start_addr, &seg->end) == 0) { if (seg->end < max_low_pfn*PAGE_SIZE ) { atomic_set(&seg->ref_count, 1); list_add(&seg->list, &dcss_list); *addr = seg->start_addr; *end = seg->end; seg->dcss_attr = rc; if (shattr == 1 && rwattr == 1) seg->shared_attr = SEGMENT_SHARED_RW; else if (shattr == 1 && rwattr == 0) seg->shared_attr = SEGMENT_SHARED_RO; else seg->shared_attr = SEGMENT_EXCLUSIVE_RW; } else { dcss_diag(DCSS_PURGESEG, seg->dcss_name, &dummy, &dummy); kfree (seg); rc = -ENOENT; } } else { kfree(seg); rc = -ENOENT; } goto out; } if (dcss_diag(DCSS_LOADNOLY, seg->dcss_name, &seg->start_addr, &seg->end) == 0) { if (seg->end < max_low_pfn*PAGE_SIZE ) { atomic_set(&seg->ref_count, 1); list_add(&seg->list, &dcss_list); *addr = seg->start_addr; *end = seg->end; seg->dcss_attr = rc; seg->shared_attr = rc; } else { dcss_diag(DCSS_PURGESEG, seg->dcss_name, &dummy, &dummy); kfree (seg); rc = -ENOENT; } } else { kfree(seg); rc = -ENOENT; } } else rc = -ENOMEM; } else { /* found */ if ((segtype == SEGMENT_EXCLUSIVE_RW) && (seg->dcss_attr != SEGMENT_EXCLUSIVE_RW)) { PRINT_ERR("Segment already loaded in other mode than EXCLUSIVE_RW!\n"); rc = -EPERM; goto out; /* reload segment in exclusive mode *//* dcss_diag(DCSS_LOADNSR, seg->dcss_name, &seg->start_addr, &seg->end); seg->dcss_attr = SEGMENT_EXCLUSIVE_RW;*/ } if ((segtype != SEGMENT_EXCLUSIVE_RW) && (seg->dcss_attr == SEGMENT_EXCLUSIVE_RW)) { PRINT_ERR("Segment already loaded in EXCLUSIVE_RW mode!\n"); rc = -EPERM; goto out; } atomic_inc(&seg->ref_count); *addr = seg->start_addr; *end = seg->end; rc = seg->dcss_attr; }out: spin_unlock(&dcss_lock); return rc;}/* * Decrease the use count of a DCSS segment and remove * it from the address space if nobody is using it * any longer. */void segment_unload(char *name){ char dcss_name[8]; unsigned long dummy; struct list_head *l,*l_tmp; struct dcss_segment *seg; if (!MACHINE_IS_VM) return; dcss_mkname(name, dcss_name); spin_lock(&dcss_lock); list_for_each_safe(l, l_tmp, &dcss_list) { seg = list_entry(l, struct dcss_segment, list); if (memcmp(seg->dcss_name, dcss_name, 8) == 0) { if (atomic_dec_return(&seg->ref_count) == 0) { /* Last user of the segment is gone. */ list_del(&seg->list); dcss_diag(DCSS_PURGESEG, seg->dcss_name, &dummy, &dummy); kfree(seg); } break; } } spin_unlock(&dcss_lock);}/* * Replace an existing DCSS segment, so that machines * that load it anew will see the new version. */void segment_replace(char *name){ char dcss_name[8]; struct list_head *l; struct dcss_segment *seg; int mybeg = 0; int myend = 0; char mybuff1[80]; char mybuff2[80]; if (!MACHINE_IS_VM) return; dcss_mkname(name, dcss_name); memset (mybuff1, 0, sizeof(mybuff1)); memset (mybuff2, 0, sizeof(mybuff2)); spin_lock(&dcss_lock); list_for_each(l, &dcss_list) { seg = list_entry(l, struct dcss_segment, list); if (memcmp(seg->dcss_name, dcss_name, 8) == 0) { mybeg = seg->start_addr >> 12; myend = (seg->end) >> 12; if (seg->shared_attr == SEGMENT_EXCLUSIVE_RW) sprintf(mybuff1, "DEFSEG %s %X-%X EW", name, mybeg, myend); if (seg->shared_attr == SEGMENT_EXCLUSIVE_RO) sprintf(mybuff1, "DEFSEG %s %X-%X RO", name, mybeg, myend); if (seg->shared_attr == SEGMENT_SHARED_RW) sprintf(mybuff1, "DEFSEG %s %X-%X SW", name, mybeg, myend); if (seg->shared_attr == SEGMENT_SHARED_RO) sprintf(mybuff1, "DEFSEG %s %X-%X SR", name, mybeg, myend); spin_unlock(&dcss_lock); sprintf(mybuff2, "SAVESEG %s", name); cpcmd(mybuff1, NULL, 80); cpcmd(mybuff2, NULL, 80); break; } } if (myend == 0) spin_unlock(&dcss_lock);}EXPORT_SYMBOL(segment_load);EXPORT_SYMBOL(segment_unload);EXPORT_SYMBOL(segment_replace);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -