/* * 该函数将指定用户态线性地址空间对应的页面以及 * 二级页表使用次数加1,并设置页面属性为只读。 * I: from - 起始线性地址; size - 内存空间大小. */ void set_shared_pages(unsigned long from, unsigned long size) { if(from & (PAGE_SIZE-1)) panic("set_shared_pages: start address with wrong alignment."); size = ALIGN_PAGE(size+PAGE_SIZE-1); if(from + size > V_USER_ZONE_END) panic("set_shared_pages: trying to set kernel address space."); /* 处理二级页表项指向的页面 */ unsigned long to, addr, tmp; for(to=from+size; from<to; from+=PAGE_SIZE) { addr = ADDR_IN_1PT(current->tss.cr3, from); if(*(unsigned long *)addr & 1) { addr = ALIGN_PAGE(*(unsigned long *)addr); addr = ADDR_IN_2PT(addr, from); if(*(unsigned long *)addr & 1) { tmp = ALIGN_PAGE(*(unsigned long *)addr); ++mem_map[M2MAP(tmp)]; *(unsigned long *)addr = tmp + P_URP; } } } /* 处理二级页表页面, from 4MB向下取整, to 4MB向上取整 */ from = (to-size) & 0xffc00000; to = (to+PAGE_SIZE/4*PAGE_SIZE-1) & 0xffc00000; for(; from<to; from+=PAGE_SIZE/4*PAGE_SIZE) { addr = ADDR_IN_1PT(current->tss.cr3, from); if(*(unsigned long *)addr & 1) { ++mem_map[M2MAP(ALIGN_PAGE(*(unsigned long *)addr))]; } } }
int m_pi_create_wc_q(struct mcm_qp *m_qp, int entries) { /* RDMA proxy WC pool, register with SCIF and IB, set pool and segm size with parameters */ m_qp->wrc.wc_sz = ALIGN_64(sizeof(struct mcm_wc_rx)); m_qp->wrc.wc_len = m_qp->wrc.wc_sz * entries; /* 64 byte aligned for signal_fence */ m_qp->wrc.wc_end = entries - 1; m_qp->wc_hd_rem = 0; m_qp->wc_tl_rem = 0; if (posix_memalign((void **)&m_qp->wrc.wc_addr, 4096, ALIGN_PAGE(m_qp->wrc.wc_len))) { mlog(0, "failed to allocate wc_rbuf, m_qp=%p, wc_len=%d, entries=%d\n", m_qp, m_qp->wrc.wc_len, entries); return -1; } memset((void*)m_qp->wrc.wc_addr, 0, ALIGN_PAGE(m_qp->wrc.wc_len)); mlog(4, " WC rbuf pool %p, LEN req=%d, act=%d\n", m_qp->wrc.wc_addr, m_qp->wrc.wc_len, ALIGN_PAGE(m_qp->wrc.wc_len)); m_qp->wc_rbuf_mr = ibv_reg_mr(m_qp->smd->md->pd, (void*)m_qp->wrc.wc_addr, m_qp->wrc.wc_len, IBV_ACCESS_LOCAL_WRITE | IBV_ACCESS_REMOTE_WRITE); if (!m_qp->wc_rbuf_mr) { mlog(0, " IB_register addr=%p,%d failed %s\n", m_qp->wrc.wc_addr, ALIGN_PAGE(m_qp->wrc.wc_len), strerror(errno)); return -1; } m_qp->wrc.wc_addr = (uint64_t)(uintptr_t)m_qp->wc_rbuf_mr->addr; m_qp->wrc.wc_rkey = m_qp->wc_rbuf_mr->rkey; mlog(4, " IB_mr for wc_buf addr %p, mr 0x%llx, len %d, entries %d rkey %x lkey %x\n", m_qp->wrc.wc_addr, m_qp->wc_rbuf_mr->addr, ALIGN_PAGE(m_qp->wrc.wc_len), entries, m_qp->wc_rbuf_mr->rkey, m_qp->wc_rbuf_mr->lkey); return 0; }
panic("do_page_fault: unknown page fault."); } } void mem_init(void) { /* 初始化进程0的代码段和数据段起止地址 */ init_proc.proc.code_start = 0; init_proc.proc.code_end = (unsigned long)&_etext; init_proc.proc.data_start = (unsigned long)&_etext; init_proc.proc.data_end = (unsigned long)&_end; /* 内存布局 */ /* 0x90002地址处保存着扩展内存大小 */ high_mem = (*(unsigned short *)0x90002+1024)*1024; d_printf("memory-size: %d Bytes.\n", high_mem); high_mem = ALIGN_PAGE(high_mem); if(high_mem >= 16*1024*1024) high_mem = 16*1024*1024; if(high_mem < 10*1024*1024) panic("the size of memory can't below 10MB."); buffer_mem_end = 3*1024*1024; buffer_mem_start = (unsigned long)&_end; /* 初始化mem_map */ memset(mem_map, (unsigned char)USED, MEM_MAP_SIZE); /* NOTE! (&mem_map)+M2MAP(buffer_mem_end) 是错误的,翻翻C语法吧 */ zeromem(&mem_map[M2MAP(buffer_mem_end)], (high_mem-buffer_mem_end)/PAGE_SIZE); /* * 将init进程(进程0)页目录表使用次数设置为1,因为
/* * 该函数将页表与内存页面挂接。 * I: page - 页面起始物理地址; * vaddr - 页面映射的虚拟线性地址; * flag - 页面属性标志. * O: 若错误,返回FALSE. */ BOOL put_page(unsigned long page, unsigned long vaddr, unsigned long flag) { if(page<buffer_mem_end || page>(high_mem-PAGE_SIZE)) panic("put_page: page address out of the limit."); if(vaddr > (V_USER_ZONE_END-PAGE_SIZE)) panic("put_page: vaddr out of the limit."); if(page & (PAGE_SIZE-1)) /* 内存页面起始地址不是PAGE_SIZE对齐 */ panic("put_page: page address with wrong alignment."); if(vaddr & (PAGE_SIZE-1)) /* 虚拟线性地址不是PAGE_SIZE对齐 */ panic("put_page: vaddr with wrong alignment."); if(flag!=P_URP && flag!=P_UWP && flag!=P_SRP && flag!=P_SWP) panic("put_page: ERROR page-flag."); /* 将要放置的页目录表项的地址 */ unsigned long put_addr = ADDR_IN_1PT(current->tss.cr3, vaddr); /* 页目录表项中P位是否置位 */ if(!(*(unsigned long *)put_addr & 1)) { unsigned long tmp; if(NULL == (tmp = get_free_page())) return FALSE; *(unsigned long *)put_addr = tmp + P_UWP; /* 用户态,读写 */ } /* 得到二级页表所在页面的首地址 */ put_addr = ALIGN_PAGE(*(unsigned long *)put_addr); /* 得到二级页表项的地址 */ put_addr = ADDR_IN_2PT(put_addr, vaddr); *(unsigned long *)put_addr = page + flag; return TRUE; }
static int hw_vm_ioctl(device *me, cpu *processor, unsigned_word cia, device_ioctl_request request, va_list ap) { /* While the caller is notified that the heap has grown by the requested amount, the heap is actually extended out to a page boundary. */ hw_vm_device *vm = (hw_vm_device*)device_data(me); switch (request) { case device_ioctl_break: { unsigned_word requested_break = va_arg(ap, unsigned_word); unsigned_word new_break = ALIGN_8(requested_break); unsigned_word old_break = vm->heap_bound; signed_word delta = new_break - old_break; if (delta > 0) vm->heap_bound = ALIGN_PAGE(new_break); break; } default: device_error(me, "Unsupported ioctl request"); break; } return 0; }
static void buddy_freelist_init(struct buddy *node, size_t nr_pages, struct page *mem_map) { extern unsigned int _ram_start; unsigned int order, idx, preserved, nr_free, n; /* Preserve the initial kernel stack to be free later, which is located * at the end of memory */ preserved = nr_pages - PAGE_NR(ALIGN_PAGE(STACK_SIZE)); order = mylog2(PAGE_NR(ALIGN_PAGE(STACK_SIZE))); SET_PAGE_ORDER(&mem_map[preserved], order); /* And mark kernel .data and .bss sections as used. * The region of mem_map array as well. */ idx = PAGE_NR(ALIGN_PAGE(&mem_map[nr_pages]) - (unsigned int)&_ram_start); nr_free = preserved - idx; debug(MSG_DEBUG, "The first free page(idx:%d) - %x", idx, &mem_map[nr_pages]); debug(MSG_DEBUG, "The number of free pages %d", nr_free); struct page *page; while (nr_free) { order = min(mylog2(idx), BUDDY_MAX_ORDER - 1); while ((int)(nr_free - (1U << order)) < 0) order--; page = &mem_map[idx]; SET_PAGE_ORDER(page, order); SET_PAGE_FLAG(page, PAGE_BUDDY); links_add(&page->list, &node->freelist[order].list); node->freelist[order].nr_pageblocks++; debug(MSG_DEBUG, "%02d %x added to %x", order, &page->list, &node->freelist[order].list); n = 1U << order; debug(MSG_DEBUG, "%04d: idx %d buddy %d head %d", n, idx, idx ^ n, idx & ~n); idx += n; nr_free -= n; node->nr_free += n; /* total pages being managed by buddy */ debug(MSG_DEBUG, "order %d, nr_free %d, next %d\n", order, nr_free, idx); } }
int m_pi_create_wr_q(struct mcm_qp *m_qp, int entries) { /* RDMA proxy WR pool, register with SCIF and IB, set pool and segm size with parameters */ m_qp->wrc.wr_sz = ALIGN_64(sizeof(struct mcm_wr_rx)); m_qp->wrc.wr_len = m_qp->wrc.wr_sz * entries; /* 64 byte aligned for signal_fence */ m_qp->wrc.wr_end = entries - 1; m_qp->wr_hd_r = 0; m_qp->wr_tl_r = 0; m_qp->wr_tl_r_wt = 1; /* start at tl+1 */ if (posix_memalign((void **)&m_qp->wrc.wr_addr, 4096, ALIGN_PAGE(m_qp->wrc.wr_len))) { mlog(0, "failed to allocate wr_rbuf, m_qp=%p, wr_len=%d, entries=%d\n", m_qp, m_qp->wrc.wr_len, entries); return -1; } memset((void*)m_qp->wrc.wr_addr, 0, ALIGN_PAGE(m_qp->wrc.wr_len)); mlog(4, " WR rbuf pool %p, LEN req=%d, act=%d\n", m_qp->wrc.wr_addr, m_qp->wrc.wr_len, ALIGN_PAGE(m_qp->wrc.wr_len) ); m_qp->wr_rbuf_mr = ibv_reg_mr(m_qp->smd->md->pd, (void*)m_qp->wrc.wr_addr, m_qp->wrc.wr_len, IBV_ACCESS_LOCAL_WRITE | IBV_ACCESS_REMOTE_WRITE); if (!m_qp->wr_rbuf_mr) { mlog(0, " IB_register addr=%p,%d failed %s\n", m_qp->wrc.wr_addr, ALIGN_PAGE(m_qp->wrc.wr_len), strerror(errno)); return -1;; } m_qp->wrc.wr_addr = (uint64_t)(uintptr_t)m_qp->wr_rbuf_mr->addr; m_qp->wrc.wr_rkey = m_qp->wr_rbuf_mr->rkey; mlog(4, " IB_mr for wr_buf addr %p, off 0x%llx, len %d, entries %d, rkey %x lkey %x\n", m_qp->wrc.wr_addr, m_qp->wr_rbuf_mr->addr, ALIGN_PAGE(m_qp->wrc.wr_len), entries, m_qp->wr_rbuf_mr->rkey, m_qp->wr_rbuf_mr->rkey); m_qp->wr_off_r = scif_register(m_qp->smd->scif_tx_ep, (void*)m_qp->wrc.wr_addr, ALIGN_PAGE(m_qp->wrc.wr_len), (off_t)0, SCIF_PROT_READ | SCIF_PROT_WRITE, 0); if (m_qp->wr_off_r == (off_t)(-1)) { mlog(0, " SCIF_register addr=%p,%d failed %s\n", m_qp->wrc.wr_addr, ALIGN_PAGE(m_qp->wrc.wr_len), strerror(errno)); return -1; } mlog(4, " WR rbuf pool %p, LEN req=%d, act=%d\n", m_qp->wr_buf, m_qp->wr_len, ALIGN_PAGE(m_qp->wrc.wr_len)); mlog(4, " SCIF_mr for wr_rbuf addr %p, off 0x%llx, len %d, entries %d\n", m_qp->wrc.wr_addr, m_qp->wr_off_r, ALIGN_PAGE(m_qp->wrc.wr_len), entries); return 0; }
* 可能没有自己独立的页目录表(因为创建进程时页目录表也是共享的),因此, * 我们还要考虑是否为其中某些进程分配页目录表。二级页表页面同样需考虑。 * I: vaddr - 发生页保护中断的页面的虚拟地址. */ BOOL un_page_wp(unsigned long vaddr) { unsigned long addr, tmp; if(vaddr >= V_KERNEL_ZONE_START) /* 用于调试内核代码 */ panic("un_page_wp: BAD, write to kernel address space."); if(vaddr < current->code_start || vaddr >= current->data_end || (vaddr >= current->code_end && vaddr < current->data_start)) panic("un_page_wp: out of code or data space limit."); /* 进程还没有自己独立的页目录表,则分配 */ if(1 < mem_map[M2MAP(current->tss.cr3)]) { addr = current->tss.cr3; if(!copy_page_dir(&(current->tss.cr3))) { k_printf("un_page_wp: have no free-page!"); return FALSE; } load_cr3(current->tss.cr3); --mem_map[M2MAP(addr)]; } addr = ADDR_IN_1PT(current->tss.cr3, vaddr); /* 进程还没有自己独立的二级页表页面,则分配 */ if(1 < mem_map[M2MAP(ALIGN_PAGE(*(unsigned long *)addr))]) { /* get_free_page而不是clean,因为接下来会复制整个页面 */ if(NULL == (tmp=get_free_page())) { k_printf("un_page_wp: have no free-page!"); return FALSE; } memcpy((char *)tmp, (char *)ALIGN_PAGE(*(unsigned long *)addr), PAGE_SIZE); --mem_map[M2MAP(ALIGN_PAGE(*(unsigned long *)addr))]; *(unsigned long *)addr = tmp + P_UWP; } addr = ALIGN_PAGE(*(unsigned long *)addr); addr = ADDR_IN_2PT(addr, vaddr); /* 最终页面引用次数为1则设置其可写,否则分配独立页面 */ if(1 == mem_map[M2MAP(ALIGN_PAGE(*(unsigned long *)addr))]) { *(unsigned long *)addr |= 0x00000002; /* 设置页面可写 */ } else { if(NULL == (tmp=get_free_page())) { k_printf("un_page_wp: have no enough memory!"); return FALSE; } memcpy((char *)tmp, (char *)ALIGN_PAGE(*(unsigned long *)addr), PAGE_SIZE); --mem_map[M2MAP(ALIGN_PAGE(*(unsigned long *)addr))]; *(unsigned long *)addr = tmp + P_UWP; } /* 刷新TLB */
int Block::mmSetPermission(uint64_t i_va, uint64_t i_size, uint64_t i_access_type) { int l_rc = 0; // Need to align the page address and the size on a page boundary. uint64_t l_aligned_va = ALIGN_PAGE_DOWN(i_va); uint64_t l_aligned_size = ALIGN_PAGE(i_size); if(!isContained(l_aligned_va)) { return (iv_nextBlock ? iv_nextBlock->mmSetPermission(i_va,i_size,i_access_type) : -EINVAL); } //printk("\n aligned VA = 0x%.lX aligned size = %ld access_type = 0x%.lX\n", l_aligned_va, l_aligned_size, i_access_type); // if i_size is zero we are only updating 1 page; increment the size to // one page. if (i_size == 0) { l_aligned_size+=PAGESIZE; } // loop through all the pages asked for based on passed aligned // Virtual address and passed in aligned size. for(uint64_t cur_page_addr = l_aligned_va; cur_page_addr < (l_aligned_va + l_aligned_size); cur_page_addr += PAGESIZE) { ShadowPTE* spte = getPTE(cur_page_addr); // if the page present need to delete the hardware // page table entry before we set permissions. if (spte->isPresent()) { // delete the hardware page table entry PageTableManager::delEntry(cur_page_addr); } if (setPermSPTE(spte, i_access_type)) { printkd(" SET PERMISSIONS.. FAILED \n"); return -EINVAL; } } return l_rc; }
/** *************************************************************************************************** * @todo Validation */ Status_e DatabaseEeprom_Write( DatabaseEeprom_Data_e DatabaseEeprom_Data, /**<[in] Index de la donnees dans la base.*/ void* pData /**<[out] Pointeur vers les donnees a ecrire.*/ ) { DatabaseEeprom_s* pDB; if (DatabaseEeprom_Data >= NB_DatabaseEeprom) return Status_KO; //-------------------------------------- // Preparation pDB = &DatabaseEeprom[DatabaseEeprom_Data]; pDB->pData = pData; //-------------------------------------- // Verif premiere lecture effectuee if(pDB->First_Read_Done == FALSE) DatabaseEeprom_Read(DatabaseEeprom_Data, pData); //-------------------------------------- // Ecriture des donnees _CONSOLE(LogId, "DatabaseEeprom_Write\n"); // Incrementation du numero de sauvegarde pDB->Num++; // Selection de l'emplacement de destination pDB->CurrentSpace++; if (pDB->CurrentSpace > 1) pDB->CurrentSpace = 0; _CONSOLE(LogId, "CurrentSpace=%d\n", pDB->CurrentSpace); // Enregistrement en EEPROM if ((pDB->CurrentSpace == 0) || (pDB->UseBkp == FALSE)) WriteData(pDB->StartAddress, pDB); else WriteData(pDB->StartAddress + ALIGN_PAGE(pDB->Size), pDB); return Status_OK; }
int m_pi_create_sr_q(struct mcm_qp *m_qp, int entries) { /* create SR queue for messages */ m_qp->sr_sz = sizeof(dat_mix_sr_t); m_qp->sr_len = m_qp->sr_sz * entries; m_qp->sr_end = entries; m_qp->sr_hd = 0; m_qp->sr_tl = 0; if (posix_memalign((void **)&m_qp->sr_buf, 4096, ALIGN_PAGE(m_qp->sr_len))) { mlog(0, "failed to allocate sr_buf, m_qp=%p, sr_len=%d, entries=%d\n", m_qp, m_qp->sr_len, entries); return -1; } memset(m_qp->sr_buf, 0, m_qp->sr_len); mlog(4, " SR rx queue - %p, qlen %d, entries %d, entry_sz %d\n", m_qp->sr_buf, m_qp->sr_len, entries, sizeof(dat_mix_sr_t)); return 0; }
grub_err_t SUFFIX (grub_freebsd_load_elf_meta) (grub_file_t file, grub_addr_t *kern_end) { grub_err_t err; Elf_Ehdr e; Elf_Shdr *s; char *shdr; unsigned symoff, stroff, symsize, strsize; grub_addr_t curload; grub_freebsd_addr_t symstart, symend, symentsize, dynamic; Elf_Sym *sym; const char *str; unsigned i; err = read_headers (file, &e, &shdr); if (err) return err; err = grub_freebsd_add_meta (FREEBSD_MODINFO_METADATA | FREEBSD_MODINFOMD_ELFHDR, &e, sizeof (e)); if (err) return err; for (s = (Elf_Shdr *) shdr; s < (Elf_Shdr *) (shdr + e.e_shnum * e.e_shentsize); s = (Elf_Shdr *) ((char *) s + e.e_shentsize)) if (s->sh_type == SHT_SYMTAB) break; if (s >= (Elf_Shdr *) ((char *) shdr + e.e_shnum * e.e_shentsize)) return grub_error (GRUB_ERR_BAD_OS, "no symbol table"); symoff = s->sh_offset; symsize = s->sh_size; symentsize = s->sh_entsize; s = (Elf_Shdr *) (shdr + e.e_shentsize * s->sh_link); stroff = s->sh_offset; strsize = s->sh_size; if (*kern_end + 4 * sizeof (grub_freebsd_addr_t) + symsize + strsize > grub_os_area_addr + grub_os_area_size) return grub_error (GRUB_ERR_OUT_OF_RANGE, "not enough memory for kernel symbols"); symstart = curload = ALIGN_UP (*kern_end, sizeof (grub_freebsd_addr_t)); *((grub_freebsd_addr_t *) UINT_TO_PTR (curload)) = symsize; curload += sizeof (grub_freebsd_addr_t); if (grub_file_seek (file, symoff) == (grub_off_t) -1) return grub_errno; sym = (Elf_Sym *) UINT_TO_PTR (curload); if (grub_file_read (file, UINT_TO_PTR (curload), symsize) != (grub_ssize_t) symsize) { if (! grub_errno) return grub_error (GRUB_ERR_BAD_OS, "invalid ELF"); return grub_errno; } curload += symsize; *((grub_freebsd_addr_t *) UINT_TO_PTR (curload)) = strsize; curload += sizeof (grub_freebsd_addr_t); if (grub_file_seek (file, stroff) == (grub_off_t) -1) return grub_errno; str = (char *) UINT_TO_PTR (curload); if (grub_file_read (file, UINT_TO_PTR (curload), strsize) != (grub_ssize_t) strsize) { if (! grub_errno) return grub_error (GRUB_ERR_BAD_OS, "invalid ELF"); return grub_errno; } curload += strsize; curload = ALIGN_UP (curload, sizeof (grub_freebsd_addr_t)); symend = curload; for (i = 0; i * symentsize < symsize; i++, sym = (Elf_Sym *) ((char *) sym + symentsize)) { const char *name = str + sym->st_name; if (grub_strcmp (name, "_DYNAMIC") == 0) break; } if (i * symentsize < symsize) { dynamic = sym->st_value; grub_dprintf ("bsd", "dynamic = %llx\n", (unsigned long long) dynamic); err = grub_freebsd_add_meta (FREEBSD_MODINFO_METADATA | FREEBSD_MODINFOMD_DYNAMIC, &dynamic, sizeof (dynamic)); if (err) return err; } err = grub_freebsd_add_meta (FREEBSD_MODINFO_METADATA | FREEBSD_MODINFOMD_SSYM, &symstart, sizeof (symstart)); if (err) return err; err = grub_freebsd_add_meta (FREEBSD_MODINFO_METADATA | FREEBSD_MODINFOMD_ESYM, &symend, sizeof (symend)); if (err) return err; *kern_end = ALIGN_PAGE (curload); return GRUB_ERR_NONE; }
grub_err_t SUFFIX (grub_freebsd_load_elfmodule_obj) (struct grub_relocator *relocator, grub_file_t file, int argc, char *argv[], grub_addr_t *kern_end) { Elf_Ehdr e; Elf_Shdr *s; char *shdr = 0; grub_addr_t curload, module; grub_err_t err; grub_size_t chunk_size = 0; void *chunk_src; err = read_headers (file, &e, &shdr); if (err) return err; curload = module = ALIGN_PAGE (*kern_end); for (s = (Elf_Shdr *) shdr; s < (Elf_Shdr *) ((char *) shdr + e.e_shnum * e.e_shentsize); s = (Elf_Shdr *) ((char *) s + e.e_shentsize)) { if (s->sh_size == 0) continue; if (s->sh_addralign) chunk_size = ALIGN_UP (chunk_size + *kern_end, s->sh_addralign) - *kern_end; chunk_size += s->sh_size; } { grub_relocator_chunk_t ch; err = grub_relocator_alloc_chunk_addr (relocator, &ch, module, chunk_size); if (err) return err; chunk_src = get_virtual_current_address (ch); } for (s = (Elf_Shdr *) shdr; s < (Elf_Shdr *) ((char *) shdr + e.e_shnum * e.e_shentsize); s = (Elf_Shdr *) ((char *) s + e.e_shentsize)) { if (s->sh_size == 0) continue; if (s->sh_addralign) curload = ALIGN_UP (curload, s->sh_addralign); s->sh_addr = curload; grub_dprintf ("bsd", "loading section to %x, size %d, align %d\n", (unsigned) curload, (int) s->sh_size, (int) s->sh_addralign); switch (s->sh_type) { default: case SHT_PROGBITS: err = load (file, (grub_uint8_t *) chunk_src + curload - *kern_end, s->sh_offset, s->sh_size); if (err) return err; break; case SHT_NOBITS: grub_memset ((grub_uint8_t *) chunk_src + curload - *kern_end, 0, s->sh_size); break; } curload += s->sh_size; } *kern_end = ALIGN_PAGE (curload); err = grub_freebsd_add_meta_module (argv[0], FREEBSD_MODTYPE_ELF_MODULE_OBJ, argc - 1, argv + 1, module, curload - module); if (! err) err = grub_bsd_add_meta (FREEBSD_MODINFO_METADATA | FREEBSD_MODINFOMD_ELFHDR, &e, sizeof (e)); if (! err) err = grub_bsd_add_meta (FREEBSD_MODINFO_METADATA | FREEBSD_MODINFOMD_SHDR, shdr, e.e_shnum * e.e_shentsize); return err; }
grub_err_t SUFFIX (grub_netbsd_load_elf_meta) (struct grub_relocator *relocator, grub_file_t file, grub_addr_t *kern_end) { grub_err_t err; Elf_Ehdr e; Elf_Shdr *s, *symsh, *strsh; char *shdr = NULL; unsigned symsize, strsize; void *sym_chunk; grub_uint8_t *curload; grub_size_t chunk_size; Elf_Ehdr *e2; struct grub_netbsd_btinfo_symtab symtab; grub_addr_t symtarget; err = read_headers (file, &e, &shdr); if (err) return err; for (s = (Elf_Shdr *) shdr; s < (Elf_Shdr *) (shdr + e.e_shnum * e.e_shentsize); s = (Elf_Shdr *) ((char *) s + e.e_shentsize)) if (s->sh_type == SHT_SYMTAB) break; if (s >= (Elf_Shdr *) ((char *) shdr + e.e_shnum * e.e_shentsize)) return GRUB_ERR_NONE; symsize = s->sh_size; symsh = s; s = (Elf_Shdr *) (shdr + e.e_shentsize * s->sh_link); strsize = s->sh_size; strsh = s; chunk_size = ALIGN_UP (symsize, sizeof (grub_freebsd_addr_t)) + ALIGN_UP (strsize, sizeof (grub_freebsd_addr_t)) + sizeof (e) + e.e_shnum * e.e_shentsize; symtarget = ALIGN_UP (*kern_end, sizeof (grub_freebsd_addr_t)); { grub_relocator_chunk_t ch; err = grub_relocator_alloc_chunk_addr (relocator, &ch, symtarget, chunk_size); if (err) return err; sym_chunk = get_virtual_current_address (ch); } symtab.nsyms = 1; symtab.ssyms = symtarget; symtab.esyms = symtarget + chunk_size; curload = sym_chunk; e2 = (Elf_Ehdr *) curload; grub_memcpy (curload, &e, sizeof (e)); e2->e_phoff = 0; e2->e_phnum = 0; e2->e_phentsize = 0; e2->e_shstrndx = 0; e2->e_shoff = sizeof (e); curload += sizeof (e); for (s = (Elf_Shdr *) shdr; s < (Elf_Shdr *) (shdr + e.e_shnum * e.e_shentsize); s = (Elf_Shdr *) ((char *) s + e.e_shentsize)) { Elf_Shdr *s2; s2 = (Elf_Shdr *) curload; grub_memcpy (curload, s, e.e_shentsize); if (s == symsh) s2->sh_offset = sizeof (e) + e.e_shnum * e.e_shentsize; else if (s == strsh) s2->sh_offset = ALIGN_UP (symsize, sizeof (grub_freebsd_addr_t)) + sizeof (e) + e.e_shnum * e.e_shentsize; else s2->sh_offset = 0; s2->sh_addr = s2->sh_offset; curload += e.e_shentsize; } if (grub_file_seek (file, symsh->sh_offset) == (grub_off_t) -1) return grub_errno; if (grub_file_read (file, curload, symsize) != (grub_ssize_t) symsize) { if (! grub_errno) return grub_error (GRUB_ERR_BAD_OS, "invalid ELF"); return grub_errno; } curload += ALIGN_UP (symsize, sizeof (grub_freebsd_addr_t)); if (grub_file_seek (file, strsh->sh_offset) == (grub_off_t) -1) return grub_errno; if (grub_file_read (file, curload, strsize) != (grub_ssize_t) strsize) { if (! grub_errno) return grub_error (GRUB_ERR_BAD_OS, "invalid ELF"); return grub_errno; } err = grub_bsd_add_meta (NETBSD_BTINFO_SYMTAB, &symtab, sizeof (symtab)); if (err) return err; *kern_end = ALIGN_PAGE (symtarget + chunk_size); return GRUB_ERR_NONE; }
grub_err_t SUFFIX (grub_freebsd_load_elf_meta) (struct grub_relocator *relocator, grub_file_t file, grub_addr_t *kern_end) { grub_err_t err; Elf_Ehdr e; Elf_Shdr *s; char *shdr = 0; unsigned symoff, stroff, symsize, strsize; grub_freebsd_addr_t symstart, symend, symentsize, dynamic; Elf_Sym *sym; void *sym_chunk; grub_uint8_t *curload; grub_freebsd_addr_t symtarget; const char *str; unsigned i; grub_size_t chunk_size; err = read_headers (file, &e, &shdr); if (err) return err; err = grub_bsd_add_meta (FREEBSD_MODINFO_METADATA | FREEBSD_MODINFOMD_ELFHDR, &e, sizeof (e)); if (err) return err; for (s = (Elf_Shdr *) shdr; s < (Elf_Shdr *) (shdr + e.e_shnum * e.e_shentsize); s = (Elf_Shdr *) ((char *) s + e.e_shentsize)) if (s->sh_type == SHT_SYMTAB) break; if (s >= (Elf_Shdr *) ((char *) shdr + e.e_shnum * e.e_shentsize)) return grub_error (GRUB_ERR_BAD_OS, "no symbol table"); symoff = s->sh_offset; symsize = s->sh_size; symentsize = s->sh_entsize; s = (Elf_Shdr *) (shdr + e.e_shentsize * s->sh_link); stroff = s->sh_offset; strsize = s->sh_size; chunk_size = ALIGN_UP (symsize + strsize, sizeof (grub_freebsd_addr_t)) + 2 * sizeof (grub_freebsd_addr_t); symtarget = ALIGN_UP (*kern_end, sizeof (grub_freebsd_addr_t)); { grub_relocator_chunk_t ch; err = grub_relocator_alloc_chunk_addr (relocator, &ch, symtarget, chunk_size); if (err) return err; sym_chunk = get_virtual_current_address (ch); } symstart = symtarget; symend = symstart + chunk_size; curload = sym_chunk; *((grub_freebsd_addr_t *) curload) = symsize; curload += sizeof (grub_freebsd_addr_t); if (grub_file_seek (file, symoff) == (grub_off_t) -1) return grub_errno; sym = (Elf_Sym *) curload; if (grub_file_read (file, curload, symsize) != (grub_ssize_t) symsize) { if (! grub_errno) return grub_error (GRUB_ERR_BAD_OS, "invalid ELF"); return grub_errno; } curload += symsize; *((grub_freebsd_addr_t *) curload) = strsize; curload += sizeof (grub_freebsd_addr_t); if (grub_file_seek (file, stroff) == (grub_off_t) -1) return grub_errno; str = (char *) curload; if (grub_file_read (file, curload, strsize) != (grub_ssize_t) strsize) { if (! grub_errno) return grub_error (GRUB_ERR_BAD_OS, "invalid ELF"); return grub_errno; } for (i = 0; i * symentsize < symsize; i++, sym = (Elf_Sym *) ((char *) sym + symentsize)) { const char *name = str + sym->st_name; if (grub_strcmp (name, "_DYNAMIC") == 0) break; } if (i * symentsize < symsize) { dynamic = sym->st_value; grub_dprintf ("bsd", "dynamic = %llx\n", (unsigned long long) dynamic); err = grub_bsd_add_meta (FREEBSD_MODINFO_METADATA | FREEBSD_MODINFOMD_DYNAMIC, &dynamic, sizeof (dynamic)); if (err) return err; } err = grub_bsd_add_meta (FREEBSD_MODINFO_METADATA | FREEBSD_MODINFOMD_SSYM, &symstart, sizeof (symstart)); if (err) return err; err = grub_bsd_add_meta (FREEBSD_MODINFO_METADATA | FREEBSD_MODINFOMD_ESYM, &symend, sizeof (symend)); if (err) return err; *kern_end = ALIGN_PAGE (symend); return GRUB_ERR_NONE; }
grub_err_t SUFFIX (grub_freebsd_load_elfmodule) (struct grub_relocator *relocator, grub_file_t file, int argc, char *argv[], grub_addr_t *kern_end) { Elf_Ehdr e; Elf_Shdr *s; char *shdr = 0; grub_addr_t curload, module; grub_err_t err; grub_size_t chunk_size = 0; void *chunk_src; err = read_headers (file, &e, &shdr); if (err) return err; curload = module = ALIGN_PAGE (*kern_end); for (s = (Elf_Shdr *) shdr; s < (Elf_Shdr *) ((char *) shdr + e.e_shnum * e.e_shentsize); s = (Elf_Shdr *) ((char *) s + e.e_shentsize)) { if (s->sh_size == 0) continue; if (! (s->sh_flags & SHF_ALLOC)) continue; if (chunk_size < s->sh_addr + s->sh_size) chunk_size = s->sh_addr + s->sh_size; } if (chunk_size < sizeof (e)) chunk_size = sizeof (e); chunk_size += e.e_phnum * e.e_phentsize; chunk_size += e.e_shnum * e.e_shentsize; { grub_relocator_chunk_t ch; err = grub_relocator_alloc_chunk_addr (relocator, &ch, module, chunk_size); if (err) return err; chunk_src = get_virtual_current_address (ch); } for (s = (Elf_Shdr *) shdr; s < (Elf_Shdr *) ((char *) shdr + e.e_shnum * e.e_shentsize); s = (Elf_Shdr *) ((char *) s + e.e_shentsize)) { if (s->sh_size == 0) continue; if (! (s->sh_flags & SHF_ALLOC)) continue; grub_dprintf ("bsd", "loading section to %x, size %d, align %d\n", (unsigned) curload, (int) s->sh_size, (int) s->sh_addralign); switch (s->sh_type) { default: case SHT_PROGBITS: err = load (file, (grub_uint8_t *) chunk_src + module + s->sh_addr - *kern_end, s->sh_offset, s->sh_size); if (err) return err; break; case SHT_NOBITS: grub_memset ((grub_uint8_t *) chunk_src + module + s->sh_addr - *kern_end, 0, s->sh_size); break; } if (curload < module + s->sh_addr + s->sh_size) curload = module + s->sh_addr + s->sh_size; } load (file, UINT_TO_PTR (module), 0, sizeof (e)); if (curload < module + sizeof (e)) curload = module + sizeof (e); load (file, UINT_TO_PTR (curload), e.e_shoff, e.e_shnum * e.e_shentsize); e.e_shoff = curload - module; curload += e.e_shnum * e.e_shentsize; load (file, UINT_TO_PTR (curload), e.e_phoff, e.e_phnum * e.e_phentsize); e.e_phoff = curload - module; curload += e.e_phnum * e.e_phentsize; *kern_end = curload; grub_freebsd_add_meta_module (argv[0], FREEBSD_MODTYPE_ELF_MODULE, argc - 1, argv + 1, module, curload - module); return SUFFIX (grub_freebsd_load_elf_meta) (relocator, file, kern_end); }
grub_err_t SUFFIX (grub_freebsd_load_elfmodule) (grub_file_t file, int argc, char *argv[], grub_addr_t *kern_end) { Elf_Ehdr e; Elf_Shdr *s; char *shdr; grub_addr_t curload, module; grub_err_t err; err = read_headers (file, &e, &shdr); if (err) return err; curload = module = ALIGN_PAGE (*kern_end); for (s = (Elf_Shdr *) shdr; s < (Elf_Shdr *) ((char *) shdr + e.e_shnum * e.e_shentsize); s = (Elf_Shdr *) ((char *) s + e.e_shentsize)) { if (s->sh_size == 0) continue; if (! (s->sh_flags & SHF_ALLOC)) continue; grub_dprintf ("bsd", "loading section to %x, size %d, align %d\n", (unsigned) curload, (int) s->sh_size, (int) s->sh_addralign); switch (s->sh_type) { default: case SHT_PROGBITS: err = load (file, UINT_TO_PTR (module + s->sh_addr), s->sh_offset, s->sh_size); if (err) return err; break; case SHT_NOBITS: if (module + s->sh_addr + s->sh_size > grub_os_area_addr + grub_os_area_size) return grub_error (GRUB_ERR_OUT_OF_RANGE, "not enough memory for the module"); grub_memset (UINT_TO_PTR (module + s->sh_addr), 0, s->sh_size); break; } if (curload < module + s->sh_addr + s->sh_size) curload = module + s->sh_addr + s->sh_size; } load (file, UINT_TO_PTR (module), 0, sizeof (e)); if (curload < module + sizeof (e)) curload = module + sizeof (e); load (file, UINT_TO_PTR (curload), e.e_shoff, e.e_shnum * e.e_shentsize); e.e_shoff = curload - module; curload += e.e_shnum * e.e_shentsize; load (file, UINT_TO_PTR (curload), e.e_phoff, e.e_phnum * e.e_phentsize); e.e_phoff = curload - module; curload += e.e_phnum * e.e_phentsize; *kern_end = curload; grub_freebsd_add_meta_module (argv[0], FREEBSD_MODTYPE_ELF_MODULE, argc - 1, argv + 1, module, curload - module); return SUFFIX (grub_freebsd_load_elf_meta) (file, kern_end); }
void AttrRP::startup(errlHndl_t& io_taskRetErrl) { errlHndl_t l_errl = NULL; do { TargetingHeader* l_header = reinterpret_cast<TargetingHeader*>( g_hostInterfaces->get_reserved_mem("ibm,hbrt-target-image")); if ((NULL == l_header) || (l_header->eyeCatcher != PNOR_TARG_EYE_CATCHER)) { /*@ * @errortype * @moduleid TARG_MOD_ATTRRP_RT * @reasoncode TARG_RC_BAD_EYECATCH * @userdata1 Observed Header Eyecatch Value * @userdata2 Memory address referenced. * * @devdesc The eyecatch value observed in memory does not * match the expected value of * PNOR_TARG_EYE_CATCHER and therefore the * contents of the Attribute sections are * unable to be parsed. * @custdesc A problem occurred during the IPL of the * system. * The eyecatch value observed in memory does not * match the expected value and therefore the * contents of the attribute sections are unable * to be parsed. */ l_errl = new ErrlEntry(ERRL_SEV_UNRECOVERABLE, TARG_MOD_ATTRRP_RT, TARG_RC_BAD_EYECATCH, NULL == l_header ? 0 : l_header->eyeCatcher, reinterpret_cast<uint64_t>(l_header)); break; } // Allocate section structures based on section count in header. iv_sectionCount = l_header->numSections; iv_sections = new AttrRP_Section[iv_sectionCount](); // Find start to the first section: // (header address + size of header + offset in header) TargetingSection* l_section = reinterpret_cast<TargetingSection*>( reinterpret_cast<uint64_t>(l_header) + sizeof(TargetingHeader) + l_header->offsetToSections ); uint64_t l_offset = 0; for (size_t i = 0; i < iv_sectionCount; ++i, ++l_section) { iv_sections[i].type = l_section->sectionType; iv_sections[i].size = l_section->sectionSize; iv_sections[i].vmmAddress = static_cast<uint64_t>( TARG_TO_PLAT_PTR(l_header->vmmBaseAddress)) + l_header->vmmSectionOffset*i; iv_sections[i].pnorAddress = reinterpret_cast<uint64_t>(l_header) + l_offset; l_offset += ALIGN_PAGE(iv_sections[i].size); TRACFCOMP(g_trac_targeting, "Decoded Attribute Section: %d, 0x%lx, 0x%lx, 0x%lx", iv_sections[i].type, iv_sections[i].vmmAddress, iv_sections[i].pnorAddress, iv_sections[i].size); } } while(false); if (l_errl) { l_errl->setSev(ERRORLOG::ERRL_SEV_UNRECOVERABLE); } io_taskRetErrl = l_errl; }
grub_err_t SUFFIX (grub_freebsd_load_elfmodule_obj) (grub_file_t file, int argc, char *argv[], grub_addr_t *kern_end) { Elf_Ehdr e; Elf_Shdr *s; char *shdr; grub_addr_t curload, module; grub_err_t err; err = read_headers (file, &e, &shdr); if (err) return err; curload = module = ALIGN_PAGE (*kern_end); for (s = (Elf_Shdr *) shdr; s < (Elf_Shdr *) ((char *) shdr + e.e_shnum * e.e_shentsize); s = (Elf_Shdr *) ((char *) s + e.e_shentsize)) { if (s->sh_size == 0) continue; if (s->sh_addralign) curload = ALIGN_UP (curload, s->sh_addralign); s->sh_addr = curload; grub_dprintf ("bsd", "loading section to %x, size %d, align %d\n", (unsigned) curload, (int) s->sh_size, (int) s->sh_addralign); switch (s->sh_type) { default: case SHT_PROGBITS: err = load (file, UINT_TO_PTR (curload), s->sh_offset, s->sh_size); if (err) return err; break; case SHT_NOBITS: if (curload + s->sh_size > grub_os_area_addr + grub_os_area_size) return grub_error (GRUB_ERR_OUT_OF_RANGE, "not enough memory for the module"); grub_memset (UINT_TO_PTR (curload), 0, s->sh_size); break; } curload += s->sh_size; } *kern_end = ALIGN_PAGE (curload); err = grub_freebsd_add_meta_module (argv[0], FREEBSD_MODTYPE_ELF_MODULE_OBJ, argc - 1, argv + 1, module, curload - module); if (! err) err = grub_freebsd_add_meta (FREEBSD_MODINFO_METADATA | FREEBSD_MODINFOMD_ELFHDR, &e, sizeof (e)); if (! err) err = grub_freebsd_add_meta (FREEBSD_MODINFO_METADATA | FREEBSD_MODINFOMD_SHDR, shdr, e.e_shnum * e.e_shentsize); return err; }
/* * 该函数将指定用户态线性地址空间对应的页面以及二级页表使用次数减1, * 若其上一级页表的引用数为1,则将其在上一级页表中的索引位置置为NULL. * I: from - 起始线性地址; size - 内存空间大小. */ void free_shared_pages(unsigned long from, unsigned long size) { if(from & (PAGE_SIZE-1)) panic("free_shared_pages: start address with wrong alignment."); size = ALIGN_PAGE(size+PAGE_SIZE-1); if(from+size > V_USER_ZONE_END) panic("free_shared_pages: trying to free kernel address space."); /* 处理二级页表项指向的页面 */ unsigned long to, addr, tmp; for(to=from+size; from<to; from+=PAGE_SIZE) { addr = ADDR_IN_1PT(current->tss.cr3, from); if(*(unsigned long *)addr & 1) { tmp = ALIGN_PAGE(*(unsigned long *)addr); addr = ADDR_IN_2PT(tmp, from); if(*(unsigned long *)addr & 1) { --mem_map[M2MAP(ALIGN_PAGE(*(unsigned long *)addr))]; if(1 == mem_map[M2MAP(tmp)]) *(unsigned long *)addr = NULL; } } } /* 处理二级页表页面 */ unsigned long begin, end; from = to - size; for(; from<to; from+=PAGE_SIZE/4*PAGE_SIZE, from&=0xffc00000) { if(!(from&(PAGE_SIZE/4*PAGE_SIZE-1)) && from+PAGE_SIZE/4*PAGE_SIZE<=to) { /* 4MB对齐,且不超出范围 */ begin = from; } else { if(!(from & (PAGE_SIZE/4*PAGE_SIZE-1))) { begin = from & 0xffc00000; end = from; } else { /* from+PAGE_SIZE/4*PAGE_SIZE > to */ begin = to; end = (to+PAGE_SIZE/4*PAGE_SIZE) & 0xffc00000; } /* 遍历其余二级页表项,若全部为空,则需将该页表引用数减1 */ for(; begin<end; begin+=PAGE_SIZE) { addr = ADDR_IN_1PT(current->tss.cr3, begin); if(*(unsigned long *)addr & 1) { addr = ALIGN_PAGE(*(unsigned long *)addr); addr = ADDR_IN_2PT(addr, begin); if(*(unsigned long *)addr & 1) break; } } if(begin < end) continue; begin = from & 0xffc00000; } /* 二级页表页面引用数减1 */ addr = ADDR_IN_1PT(current->tss.cr3, begin); if(*(unsigned long *)addr & 1) { --mem_map[M2MAP(ALIGN_PAGE(*(unsigned long *)addr))]; if(1 == mem_map[M2MAP(current->tss.cr3)]) *(unsigned long *)addr = NULL; } } }
errlHndl_t validateDrtmPayload() { SB_ENTER("validateDrtmPayload"); errlHndl_t pError = nullptr; const void* drtmPayloadVirtAddr = nullptr; do { bool drtmMpIpl = false; isDrtmMpipl(drtmMpIpl); if(drtmMpIpl) { SB_DBG("validateDrtmPayload: DRTM active, validating DRTM payload." "proc chips."); TARGETING::Target* pSysTarget = nullptr; TARGETING::targetService().getTopLevelTarget(pSysTarget); if(pSysTarget == nullptr) { // TODO: RTC 167205: GA error handling assert(false,"validateDrtmPayload: BUG! nullptr system target " "detected"); break; } const auto drtmPayloadPhysAddrMb = pSysTarget->getAttr< TARGETING::ATTR_DRTM_PAYLOAD_ADDR_MB_HB>(); if(drtmPayloadPhysAddrMb == 0) { assert(false,"validateDrtmPayload: BUG! DRTM payload physical " "address should not be 0."); break; } const uint64_t drtmPayloadPhysAddr = drtmPayloadPhysAddrMb*BYTES_PER_MEGABYTE; SB_INF("validateDrtmPayload: DRTM payload available at physical " "address of %d MB (0x%16llX).", drtmPayloadPhysAddrMb,drtmPayloadPhysAddr); // Compute DRTM payload size // TODO: RTC 167205: Once the DRTM save area is known/defined, // need to figure out a better initial size to map. For example, // perhaps we map just one page to begin with, in order to read out // the actual total size. Also, a size is available, assert if the // size is 0. uint64_t drtmPayloadSize = 0; #ifdef CONFIG_DRTM_TRIGGERING drtmPayloadSize = ALIGN_PAGE(sizeof(DRTM_RIT_PAYLOAD)); #endif // Map in the physical memory to virtual memory drtmPayloadVirtAddr = mm_block_map ( reinterpret_cast<void*>(drtmPayloadPhysAddr),drtmPayloadSize); if(drtmPayloadVirtAddr == nullptr) { // TODO: RTC 167205: GA error handling assert(false,"validateDrtmPayload: BUG! mm_block_map returned " "nullptr for physical address 0x%016llX and size " "0x%016llX.", drtmPayloadPhysAddr,drtmPayloadSize); break; } #ifdef CONFIG_DRTM_TRIGGERING // Verify the payload matches expected result if(memcmp(drtmPayloadVirtAddr,DRTM_RIT_PAYLOAD, sizeof(DRTM_RIT_PAYLOAD) != 0)) { const uint32_t* pAddrAct = reinterpret_cast<const uint32_t*>( drtmPayloadVirtAddr); const uint32_t* pAddrExp = reinterpret_cast<const uint32_t*>( &DRTM_RIT_PAYLOAD); SB_ERR("validateDrtmPayload: DRTM RIT: payload content at " "0x%16llX was not as expected. Expected value = 0x%08X, " "actual = 0x%08X", drtmPayloadVirtAddr, *pAddrAct, *pAddrExp); // TODO: RTC 167205: GA error handling assert(false,"validateDrtmPayload: BUG: DRTM payload content " "at 0x%16llX was not as expected. Expected value = " "0x%08X, actual = 0x%08X", drtmPayloadVirtAddr, *pAddrAct, *pAddrExp); break; } // Extend (arbitrary) measurement to PCR17 SHA512_t hash = {0}; memcpy(hash,DRTM_RIT_PAYLOAD,sizeof(DRTM_RIT_PAYLOAD)); pError = TRUSTEDBOOT::pcrExtend(TRUSTEDBOOT::PCR_DRTM_17, TRUSTEDBOOT::EV_COMPACT_HASH, hash, sizeof(SHA512_t),DRTM_RIT_LOG_TEXT); if(pError) { SB_ERR("validateDrtmPayload: Failed in pcrExtend() for PCR 17"); break; } #else // TODO: RTC 167205: Securely verify the measured launch environment // TODO: RTC 167205: Really measure+extend the payload #endif } else { SB_INF("validateDrtmPayload: DRTM not active, skipping DRTM " "payload verification "); } } while(0); if(drtmPayloadVirtAddr) { auto rc = mm_block_unmap(const_cast<void*>(drtmPayloadVirtAddr)); if(rc != 0) { // TODO: RTC 167205: GA error handling assert(false,"validateDrtmPayload: BUG! mm_block_unmap failed for " "virtual address 0x%16llX.", drtmPayloadVirtAddr); } } if(pError) { SB_ERR("validateDrtmPayload: plid=0x%08X, eid=0x%08X, reason=0x%04X", ERRL_GETPLID_SAFE(pError), ERRL_GETEID_SAFE(pError), ERRL_GETRC_SAFE(pError)); } SB_EXIT("validateDrtmPayload"); return pError; }
/** *************************************************************************************************** * @todo Validation */ Status_e DatabaseEeprom_Read( DatabaseEeprom_Data_e DatabaseEeprom_Data, /**<[in] Index de la donnees dans la base.*/ void* pData /**<[out] Pointeur vers les donnees lues.*/ ) { DatabaseEeprom_s* pDB; Bool_e Data0_valide; Bool_e Data1_valide; uint8_t Num0; uint8_t Num1; int8_t ChoixData = (-1); if (DatabaseEeprom_Data >= NB_DatabaseEeprom) return Status_KO; //-------------------------------------- // Preparation pDB = &DatabaseEeprom[DatabaseEeprom_Data]; pDB->pData = pData; if(!pDB->First_Read_Done) { pDB->First_Read_Done = TRUE; } //-------------------------------------- // Lecture des donnees _CONSOLE(LogId, "DatabaseEeprom_Read\n"); // Lecture et verification Data0 ReadData(pDB->StartAddress, pDB); Num0 = pDB->Num; Data0_valide = IsValide(pDB); // Si pas de backup utilise on sort de suite if (pDB->UseBkp == FALSE) { if (Data0_valide) return Status_OK; else return Status_KO; } // Lecture et verification Data1 si utilise ReadData(pDB->StartAddress + ALIGN_PAGE(pDB->Size+2), pDB); Num1 = pDB->Num; Data1_valide = IsValide(pDB); _CONSOLE(LogId, "Data0: Num=%d | IsValide=%d\n", Num0, Data0_valide); _CONSOLE(LogId, "Data1: Num=%d | IsValide=%d\n", Num1, Data1_valide); //-------------------------------------- // Choix de la data a conserver if (Data0_valide && Data1_valide) // 2 Data valides (on prend le plus recente) { _CONSOLE(LogId, "Data0 et Data1 valides: "); if ((Num0 == 0) && (Num1 == 0xFF)) ChoixData = 0; else if ((Num0 == 0xFF) && (Num1 == 0)) ChoixData = 1; else if (Num0 > Num1) ChoixData = 0; else ChoixData = 1; } else if (Data0_valide && !Data1_valide) // Seule la Data0 est valide ChoixData = 0; else if (!Data0_valide && Data1_valide) // Seule la Data1 est valide ChoixData = 1; else // Aucune Data valide... ChoixData = (-1); switch (ChoixData) { case 0: _CONSOLE(LogId, "utilisation de Data0.\n"); ReadData(pDB->StartAddress, pDB); // Relecture de Data0 pDB->CurrentSpace = 0; break; case 1: _CONSOLE(LogId, "utilisation de Data1.\n"); // Relecture inutile (deja stockee dans pData) pDB->CurrentSpace = 1; break; case (-1): default: _CONSOLE(LogId, "Aucune Data valide. Restauration des valeurs par defaut.\n"); if (pDB->pDefaultData != NULL) { memcpy(pDB->pData, pDB->pDefaultData, pDB->Size); pDB->CurrentSpace = 1; DatabaseEeprom_Write(DatabaseEeprom_Data, pData); } return Status_KO; break; } return Status_OK; }
int Block::removePages(VmmManager::PAGE_REMOVAL_OPS i_op, void* i_vaddr, uint64_t i_size, task_t* i_task) { uint64_t l_vaddr = reinterpret_cast<uint64_t>(i_vaddr); //Align virtual address & size to page boundary /*The given virtual address will be 'rounded' down to the nearest page boundary, along with the given size will be 'rounded' up to the nearest divisible page size.*/ uint64_t l_aligned_va = ALIGN_PAGE_DOWN(l_vaddr); uint64_t l_aligned_size = ALIGN_PAGE(i_size); //Find block containing virtual address if(!this->isContained(l_aligned_va)) { return (iv_nextBlock ? iv_nextBlock->removePages(i_op,i_vaddr,i_size,i_task):-EINVAL); } else if ((l_aligned_va+l_aligned_size) > (this->iv_baseAddr+this->iv_size)) { return -EINVAL; } //Perform requested page removal operation for (l_vaddr = l_aligned_va;l_vaddr < (l_aligned_va+l_aligned_size); l_vaddr+= PAGESIZE) { ShadowPTE* pte = getPTE(l_vaddr); uint64_t pageAddr = pte->getPageAddr(); if (pte->isPresent() && (0 != pageAddr)) { //Delete from HW page table immediately PageTableManager::delEntry(l_vaddr); if (pte->isDirty() && pte->isWriteTracked() && this->iv_writeMsgHdlr != NULL) { releaseSPTE(pte); //Send write msg with the page address if (i_task != NULL) { this->iv_writeMsgHdlr->incMsgCount(i_task); } this->iv_writeMsgHdlr->addVirtAddr( reinterpret_cast<void*>(l_vaddr),pageAddr); this->iv_writeMsgHdlr->sendMessage(MSG_MM_RP_WRITE, reinterpret_cast<void*>(l_vaddr), reinterpret_cast<void*>(pageAddr),i_task); } else if (pte->isDirty() && !pte->isWriteTracked() && i_op == VmmManager::EVICT) { //Skip page } else if (i_op != VmmManager::FLUSH) { //'Release' page entry releaseSPTE(pte); PageManager::freePage(reinterpret_cast<void*>(pageAddr)); } } } return 0; }
HdatSpiraS::HdatSpiraS(const hdatMsAddr_t &i_msAddr) : iv_spirasSize(0), iv_spiras(NULL) { HDAT_ENTER(); iv_spirasSize = sizeof(hdatSpiraS_t); uint64_t l_base_addr = ((uint64_t) i_msAddr.hi << 32) | i_msAddr.lo; HDAT_DBG("l_base_addr at SPIRA-S=0x%016llX",l_base_addr); //calculate the hrmor and add to base address TARGETING::Target * sys = NULL; TARGETING::targetService().getTopLevelTarget( sys ); assert(sys != NULL); uint64_t l_hrmor = sys->getAttr<TARGETING::ATTR_PAYLOAD_BASE>()*MEGABYTE; HDAT_DBG("HRMOR=0x%08x",l_hrmor); l_base_addr = l_hrmor + l_base_addr; HDAT_DBG("base address after adding HRMOR=0x%08x",l_base_addr); uint64_t l_base_addr_down = ALIGN_PAGE_DOWN(l_base_addr); HDAT_DBG("l_base_addr_down=0x%016llX",l_base_addr_down); HDAT_DBG("reqd space=0x%x, will do a block map of size 0x%x", iv_spirasSize, ALIGN_PAGE(iv_spirasSize)); void *l_virt_addr = mm_block_map( reinterpret_cast<void*>(l_base_addr_down), ALIGN_PAGE(iv_spirasSize) + PAGESIZE); HDAT_DBG("l_virt_addr=0x%016llX after block map",l_virt_addr); uint64_t l_vaddr = reinterpret_cast<uint64_t>(l_virt_addr); HDAT_DBG("will add offset %x to starting virtual address", (l_base_addr-l_base_addr_down)); l_vaddr += l_base_addr-l_base_addr_down; HDAT_DBG("l_vaddr after adding=0x%016llX",l_vaddr); l_virt_addr = reinterpret_cast<void *>(l_vaddr); HDAT_DBG("l_virt_addr=0x%016llX",l_virt_addr); iv_spiras = reinterpret_cast<hdatSpiraS_t *>(l_virt_addr); HDAT_DBG("constructor iv_spiras addr 0x%016llX virtual addr 0x%016llX,space" " allocated=0x%x",(uint64_t) this->iv_spiras, (uint64_t)l_virt_addr,iv_spirasSize); HDAT_DBG("creating SPIRA-S header"); setSpiraSHdrs(); HDAT_DBG("done setting the SPIRA-S header"); iv_spiras->hdatHDIF.hdatSize = sizeof(hdatSpira_t); HDAT_EXIT(); return; }