Ejemplo n.º 1
0
uintptr_t OS::heap_max() {
  // Before the memory map is populated
  if (UNLIKELY(memory_map().empty()))
    return heap_max_;

  // After memory map is populated
  return memory_map().at(heap_begin).addr_end();
}
Ejemplo n.º 2
0
EFI_STATUS 
print_memory_map(void)
{
    EFI_MEMORY_DESCRIPTOR *buf;
    UINTN desc_size;
    UINT32 desc_version;
    UINTN size, map_key, mapping_size;
    EFI_MEMORY_DESCRIPTOR *desc;
    EFI_STATUS err = EFI_SUCCESS;
    int i = 0;

    err = memory_map(&buf, &size, &map_key, &desc_size, &desc_version);
    if (err != EFI_SUCCESS)
        return err;

    Print(L"Memory Map Size: %d\n", size);
    Print(L"Map Key: %d\n", map_key);
    Print(L"Descriptor Version: %d\n", desc_version);
    Print(L"Descriptor Size: %d\n\n", desc_size);

    desc = buf;
    while ((void *)desc < (void *)buf + size) {
        mapping_size = desc->NumberOfPages * PAGE_SIZE;

        Print(L"[#%02d] Type: %s  Attr: 0x%x\n", i, memory_type_to_str(desc->Type), desc->Attribute);
        Print(L"      Phys: %016llx-%016llx\n", desc->PhysicalStart, desc->PhysicalStart + mapping_size);
        Print(L"      Virt: %016llx-%016llx\n\n", desc->VirtualStart, desc->VirtualStart + mapping_size);

        desc = (void *)desc + desc_size;
        i++;
    }

    uefi_call_wrapper(BS->FreePool, 1, buf);
    return err;
}
Ejemplo n.º 3
0
static inline int zcb_alloc (
	struct conn_info *conn_info,
	const char *path_to_file,
	size_t size,
	void **addr)
{
	struct zcb_mapped *zcb_mapped;
	unsigned int res;

	zcb_mapped = malloc (sizeof (struct zcb_mapped));
	if (zcb_mapped == NULL) {
		return (-1);
	}

	res = memory_map (
		path_to_file,
		size,
		addr);
	if (res == -1) {
		free (zcb_mapped);
		return (-1);
	}

	list_init (&zcb_mapped->list);
	zcb_mapped->addr = *addr;
	zcb_mapped->size = size;
	list_add_tail (&zcb_mapped->list, &conn_info->zcb_mapped_list_head);
	return (0);
}
Ejemplo n.º 4
0
static
void cds_lfht_alloc_bucket_table(struct cds_lfht *ht, unsigned long order)
{
	if (order == 0) {
		if (ht->min_nr_alloc_buckets == ht->max_nr_buckets) {
			/* small table */
			ht->tbl_mmap = calloc(ht->max_nr_buckets,
					sizeof(*ht->tbl_mmap));
			assert(ht->tbl_mmap);
			return;
		}
		/* large table */
		ht->tbl_mmap = memory_map(ht->max_nr_buckets
			* sizeof(*ht->tbl_mmap));
		memory_populate(ht->tbl_mmap,
			ht->min_nr_alloc_buckets * sizeof(*ht->tbl_mmap));
	} else if (order > ht->min_alloc_buckets_order) {
		/* large table */
		unsigned long len = 1UL << (order - 1);

		assert(ht->min_nr_alloc_buckets < ht->max_nr_buckets);
		memory_populate(ht->tbl_mmap + len,
				len * sizeof(*ht->tbl_mmap));
	}
	/* Nothing to do for 0 < order && order <= ht->min_alloc_buckets_order */
}
/**
 * emalloc - Allocate memory with a strict alignment requirement
 * @size: size in bytes of the requested allocation
 * @align: the required alignment of the allocation
 * @addr: a pointer to the allocated address on success
 *
 * If we cannot satisfy @align we return 0.
 */
EFI_STATUS emalloc(UINTN size, UINTN align, EFI_PHYSICAL_ADDRESS *addr)
{
        UINTN map_size, map_key, desc_size;
        EFI_MEMORY_DESCRIPTOR *map_buf;
        UINTN d, map_end;
        UINT32 desc_version;
        EFI_STATUS err;
        UINTN nr_pages = EFI_SIZE_TO_PAGES(size);

        err = memory_map(&map_buf, &map_size, &map_key,
                         &desc_size, &desc_version);
        if (err != EFI_SUCCESS)
                goto fail;

        d = (UINTN)map_buf;
        map_end = (UINTN)map_buf + map_size;

        for (; d < map_end; d += desc_size) {
                EFI_MEMORY_DESCRIPTOR *desc;
                EFI_PHYSICAL_ADDRESS start, end, aligned;

                desc = (EFI_MEMORY_DESCRIPTOR *)d;
                if (desc->Type != EfiConventionalMemory)
                        continue;

                if (desc->NumberOfPages < nr_pages)
                        continue;

                start = desc->PhysicalStart;
                end = start + (desc->NumberOfPages << EFI_PAGE_SHIFT);

                /* Low-memory is super-precious! */
                if (end <= 1 << 20)
                        continue;
                if (start < 1 << 20) {
                        size -= (1 << 20) - start;
                        start = (1 << 20);
                }

                aligned = (start + align -1) & ~(align -1);

                if ((aligned + size) <= end) {
                        err = allocate_pages(AllocateAddress, EfiLoaderData,
                                             nr_pages, &aligned);
                        if (err == EFI_SUCCESS) {
                                *addr = aligned;
                                break;
                        }
                }
        }

        if (d == map_end)
                err = EFI_OUT_OF_RESOURCES;

        free_pool(map_buf);
fail:
        return err;
}
Ejemplo n.º 6
0
Archivo: mbc1.c Proyecto: bogger33/emus
void mbc1_rom_bank_number_write(uint16_t address, uint8_t data)
{
	uint8_t lower = data & ROM_BANK_NUMBER_LOWER_MASK;
	if (lower == 0)
		lower = 1;
	rom1_bank_number &= ~ROM_BANK_NUMBER_LOWER_MASK;
	rom1_bank_number |= lower;
	memory_map((char *)gb_get_cart_path(), (void *)rom1, rom1_bank_number * ROM1_BANK_SIZE, ROM1_BANK_SIZE);
}
Ejemplo n.º 7
0
Archivo: mbc1.c Proyecto: bogger33/emus
void mbc1_ram_rom_bank_number_write(uint16_t address, uint8_t data)
{
	if (!mode_select) {
		uint8_t upper = data << ROM_BANK_NUMBER_UPPER_SHIFT;
		rom1_bank_number &= ~ROM_BANK_NUMBER_UPPER_MASK;
		rom1_bank_number |= upper;
		memory_map((char *)gb_get_cart_path(), (void *)rom1, rom1_bank_number * ROM1_BANK_SIZE, ROM1_BANK_SIZE);
	} else {
		ram_bank_number = data;
	}
}
Ejemplo n.º 8
0
void process_init(void) {
    // Map the thread map
    uintptr_t vaddr = MEMORY_PROCESS_MAP_VADDR;
    uint16_t pflags = PAGE_FLAG_GLOBAL | PAGE_FLAG_WRITEABLE;
    uintptr_t offset;

    for (offset = 0; offset < PROCESS_MAP_SIZE; offset += 0x1000)
        memory_map(vaddr + offset, frame_alloc(), pflags);

    // Clear the thread map
    memset((void *) vaddr, 0, PROCESS_MAP_SIZE);
}
Ejemplo n.º 9
0
static void _process_create_thread_map(uint32_t pid) {
    // Map thread map
    uintptr_t thread_map = MEMORY_THREAD_MAP_VADDR + pid * THREAD_MAP_SIZE;
    uint16_t pflags = PAGE_FLAG_WRITEABLE | PAGE_FLAG_GLOBAL;
    size_t offset;

    for (offset = 0; offset < THREAD_MAP_SIZE; offset += 0x1000)
        memory_map(thread_map + offset, frame_alloc(), pflags);

    // Clear thread map
    memset((void *) thread_map, 0, THREAD_MAP_SIZE);
}
Ejemplo n.º 10
0
static EFI_STATUS print_memory_map(void)
{
	EFI_MEMORY_DESCRIPTOR *buf;
	UINTN desc_size;
	UINT32 desc_version;
	UINTN size, map_key;
	EFI_MEMORY_DESCRIPTOR *desc;
	EFI_STATUS err;
	int i;

	err = memory_map(&buf, &size, &map_key,
			 &desc_size, &desc_version);
	if (err != EFI_SUCCESS)
		return err;

	Print(L"System Memory Map\n");
	Print(L"System Memory Map Size: %d\n", size);
	Print(L"Descriptor Version: %d\n", desc_version);
	Print(L"Descriptor Size: %d\n", desc_size);

	desc = buf;
	i = 0;

	while ((void *)desc < (void *)buf + size) {
		UINTN mapping_size;

		mapping_size = desc->NumberOfPages * PAGE_SIZE;

		Print(L"[#%.2d] Type: %s\n", i,
		      memory_type_to_str(desc->Type));

		Print(L"      Attr: 0x%016llx\n", desc->Attribute);

		Print(L"      Phys: [0x%016llx - 0x%016llx]\n",
		      desc->PhysicalStart,
		      desc->PhysicalStart + mapping_size);

		Print(L"      Virt: [0x%016llx - 0x%016llx]",
		      desc->VirtualStart,
		      desc->VirtualStart + mapping_size);

		Print(L"\n");
		desc = (void *)desc + desc_size;
		i++;
	}

	free_pool(buf);
	return err;
}
Ejemplo n.º 11
0
Archivo: pass2.c Proyecto: wacke/g21k
void pass2( void )
{
   memory_check();

   process_section_list();

   allocate();

   update_linker_information();

   output_object();

   if( mflag )
       memory_map();
}
Ejemplo n.º 12
0
cs_error_t
coroipcc_zcb_alloc (
	hdb_handle_t handle,
	void **buffer,
	size_t size,
	size_t header_size)
{
	struct ipc_instance *ipc_instance;
	void *buf = NULL;
	char path[PATH_MAX];
	unsigned int res;
	mar_req_coroipcc_zc_alloc_t req_coroipcc_zc_alloc;
	coroipc_response_header_t res_coroipcs_zc_alloc;
	size_t map_size;
	struct iovec iovec;
	struct coroipcs_zc_header *hdr;

	res = hdb_error_to_cs (hdb_handle_get (&ipc_hdb, handle, (void **)&ipc_instance));
	if (res != CS_OK) {
		return (res);
	}
	map_size = size + header_size + sizeof (struct coroipcs_zc_header);
	res = memory_map (path, "corosync_zerocopy-XXXXXX", &buf, map_size);
	assert (res != -1);

	req_coroipcc_zc_alloc.header.size = sizeof (mar_req_coroipcc_zc_alloc_t);
	req_coroipcc_zc_alloc.header.id = ZC_ALLOC_HEADER;
	req_coroipcc_zc_alloc.map_size = map_size;
	strcpy (req_coroipcc_zc_alloc.path_to_file, path);


	iovec.iov_base = (void *)&req_coroipcc_zc_alloc;
	iovec.iov_len = sizeof (mar_req_coroipcc_zc_alloc_t);

	res = coroipcc_msg_send_reply_receive (
		handle,
		&iovec,
		1,
		&res_coroipcs_zc_alloc,
		sizeof (coroipc_response_header_t));

	hdr = (struct coroipcs_zc_header *)buf;
	hdr->map_size = map_size;
	*buffer = ((char *)buf) + sizeof (struct coroipcs_zc_header);

	hdb_handle_put (&ipc_hdb, handle);
	return (res);
}
Ejemplo n.º 13
0
void OS::legacy_boot()
{
  // Fetch CMOS memory info (unfortunately this is maximally 10^16 kb)
  auto mem = x86::CMOS::meminfo();
  if (OS::memory_end_ == 0)
  {
    //uintptr_t low_memory_size = mem.base.total * 1024;
    INFO2("* Low memory: %i Kib", mem.base.total);

    uintptr_t high_memory_size = mem.extended.total * 1024;
    INFO2("* High memory (from cmos): %i Kib", mem.extended.total);
    OS::memory_end_ = 0x100000 + high_memory_size - 1;
  }

  auto& memmap = memory_map();
  // No guarantees without multiboot, but we assume standard memory layout
  memmap.assign_range({0x0009FC00, 0x0009FFFF,
        "EBDA"});
  memmap.assign_range({0x000A0000, 0x000FFFFF,
        "VGA/ROM"});

}
Ejemplo n.º 14
0
Archivo: stack.c Proyecto: zrho/Carbon
void stack_resize(stack_t *stack, uintptr_t new_len, process_t *process) {
    // Check address space
    if (UNLIKELY(process->addr_space != memory_space_get()))
    	PANIC("Failed trying to resize a stack for a process while not being in "
    	      "its address space.");

    // Greater than maximum length?
    if (UNLIKELY(new_len > STACK_LENGTH_MAX))
        PANIC("Failed trying to increase a stack's size over the maximum stack "
            "size.");

    // Size increased or decreased?
    if (new_len > stack->length) { // Increased
        // Map region
        uintptr_t reg_end = stack->address - stack->length;
        uintptr_t reg_addr;
        uint16_t flags = PAGE_FLAG_WRITEABLE | PAGE_FLAG_USER;

        for (reg_addr = stack->address - new_len; reg_addr < reg_end; reg_addr += PAGE_SIZE) {
        	uintptr_t phys = frame_alloc();
            memory_map(reg_addr, phys, flags);
        }

    } else if (new_len < stack->length) {
        // Unmap region
        uintptr_t reg_end = stack->address - new_len;
        uintptr_t reg_addr;

        for (reg_addr = stack->address - stack->length; reg_addr < reg_end; reg_addr += 0x1000) {
            uintptr_t phys = memory_physical(reg_addr);
            memory_unmap(reg_addr);
            frame_free(phys);
        }
    }

    // Set new size
    stack->length = new_len;
}
Ejemplo n.º 15
0
Archivo: mbc1.c Proyecto: bogger33/emus
void mbc1_rom0_init()
{
	memory_map((char *)gb_get_bios_path(), (void *)rom0, 0, BIOS_SIZE);
	memory_map((char *)gb_get_cart_path(), (void *)&rom0[BIOS_SIZE], BIOS_SIZE, ROM0_BANK_SIZE - BIOS_SIZE);
}
Ejemplo n.º 16
0
Archivo: mbc1.c Proyecto: bogger33/emus
void mbc1_lock_bios()
{
	memory_map((char *)gb_get_cart_path(), (void *)rom0, 0, BIOS_SIZE);
}
Ejemplo n.º 17
0
Archivo: mbc1.c Proyecto: bogger33/emus
void mbc1_rom_bank_number_init()
{
	rom1_bank_number = 1;
	memory_map((char *)gb_get_cart_path(), (void *)rom1, rom1_bank_number * ROM1_BANK_SIZE, ROM1_BANK_SIZE);
}
Ejemplo n.º 18
0
Archivo: rom.c Proyecto: bogger33/emus
void rom_init(char *rom_path)
{
	memory_map((char *)gb_get_bios_path(), (void *)rom, 0, BIOS_SIZE);
	memory_map((char *)gb_get_cart_path(), (void *)&rom[BIOS_SIZE], BIOS_SIZE, ROM_SIZE - BIOS_SIZE);
}
Ejemplo n.º 19
0
void OS::start(char* _cmdline, uintptr_t mem_size)
{
  // Initialize stdout handlers
  OS::add_stdout(&OS::default_stdout);

  PROFILE("");
  // Print a fancy header
  CAPTION("#include<os> // Literally");

  void* esp = get_cpu_esp();
  MYINFO("Stack: %p", esp);

  /// STATMAN ///
  /// initialize on page 7, 2 pages in size
  Statman::get().init(0x6000, 0x3000);

  OS::cmdline = _cmdline;

  // setup memory and heap end
  OS::memory_end_ = mem_size;
  OS::heap_max_ = OS::memory_end_;

  // Call global ctors
  PROFILE("Global constructors");
  __libc_init_array();


  PROFILE("Memory map");
  // Assign memory ranges used by the kernel
  auto& memmap = memory_map();
  MYINFO("Assigning fixed memory ranges (Memory map)");

  memmap.assign_range({0x500, 0x5fff, "solo5", "solo5"});
  memmap.assign_range({0x6000, 0x8fff, "Statman", "Statistics"});
  memmap.assign_range({0xA000, 0x9fbff, "Stack", "Kernel / service main stack"});
  memmap.assign_range({(uintptr_t)&_LOAD_START_, (uintptr_t)&_end,
        "ELF", "Your service binary including OS"});

  Expects(::heap_begin and heap_max_);
  // @note for security we don't want to expose this
  memmap.assign_range({(uintptr_t)&_end + 1, ::heap_begin - 1,
        "Pre-heap", "Heap randomization area"});

  uintptr_t span_max = std::numeric_limits<std::ptrdiff_t>::max();
  uintptr_t heap_range_max_ = std::min(span_max, heap_max_);

  MYINFO("Assigning heap");
  memmap.assign_range({::heap_begin, heap_range_max_,
        "Heap", "Dynamic memory", heap_usage });

  MYINFO("Printing memory map");
  for (const auto &i : memmap)
    INFO2("* %s",i.second.to_string().c_str());

  extern void __platform_init();
  __platform_init();

  MYINFO("Booted at monotonic_ns=%lld walltime_ns=%lld",
         solo5_clock_monotonic(), solo5_clock_wall());

  Solo5_manager::init();

  // We don't need a start or stop function in solo5.
  Timers::init(
    // timer start function
    [] (std::chrono::microseconds) {},
    // timer stop function
    [] () {});

  // Some tests are asserting there is at least one timer that is always ON
  // (the RTC calibration timer). Let's fake some timer so those tests pass.
  Timers::oneshot(std::chrono::hours(1000000), [] (auto) {});

  Timers::ready();
}
Ejemplo n.º 20
0
/*
 * External API
 */
cs_error_t
coroipcc_service_connect (
	const char *socket_name,
	unsigned int service,
	size_t request_size,
	size_t response_size,
	size_t dispatch_size,
	hdb_handle_t *handle)

{
	int request_fd;
	struct sockaddr_un address;
	cs_error_t res;
	struct ipc_instance *ipc_instance;
#if _POSIX_THREAD_PROCESS_SHARED < 1
	key_t semkey = 0;
	union semun semun;
#endif
	int sys_res;
	mar_req_setup_t req_setup;
	mar_res_setup_t res_setup;
	char control_map_path[PATH_MAX];
	char request_map_path[PATH_MAX];
	char response_map_path[PATH_MAX];
	char dispatch_map_path[PATH_MAX];

	res = hdb_error_to_cs (hdb_handle_create (&ipc_hdb,
		sizeof (struct ipc_instance), handle));
	if (res != CS_OK) {
		return (res);
	}

	res = hdb_error_to_cs (hdb_handle_get (&ipc_hdb, *handle, (void **)&ipc_instance));
	if (res != CS_OK) {
		return (res);
	}

	res_setup.error = CS_ERR_LIBRARY;

#if defined(COROSYNC_SOLARIS)
	request_fd = socket (PF_UNIX, SOCK_STREAM, 0);
#else
	request_fd = socket (PF_LOCAL, SOCK_STREAM, 0);
#endif
	if (request_fd == -1) {
		return (CS_ERR_LIBRARY);
	}
#ifdef SO_NOSIGPIPE
	socket_nosigpipe (request_fd);
#endif

	memset (&address, 0, sizeof (struct sockaddr_un));
	address.sun_family = AF_UNIX;
#if defined(COROSYNC_BSD) || defined(COROSYNC_DARWIN)
	address.sun_len = SUN_LEN(&address);
#endif

#if defined(COROSYNC_LINUX)
	sprintf (address.sun_path + 1, "%s", socket_name);
#else
	sprintf (address.sun_path, "%s/%s", SOCKETDIR, socket_name);
#endif
	sys_res = connect (request_fd, (struct sockaddr *)&address,
		COROSYNC_SUN_LEN(&address));
	if (sys_res == -1) {
		res = CS_ERR_TRY_AGAIN;
		goto error_connect;
	}

	sys_res = memory_map (
		control_map_path,
		"control_buffer-XXXXXX",
		(void *)&ipc_instance->control_buffer,
		8192);
	if (sys_res == -1) {
		res = CS_ERR_LIBRARY;
		goto error_connect;
	}

	sys_res = memory_map (
		request_map_path,
		"request_buffer-XXXXXX",
		(void *)&ipc_instance->request_buffer,
		request_size);
	if (sys_res == -1) {
		res = CS_ERR_LIBRARY;
		goto error_request_buffer;
	}

	sys_res = memory_map (
		response_map_path,
		"response_buffer-XXXXXX",
		(void *)&ipc_instance->response_buffer,
		response_size);
	if (sys_res == -1) {
		res = CS_ERR_LIBRARY;
		goto error_response_buffer;
	}

	sys_res = circular_memory_map (
		dispatch_map_path,
		"dispatch_buffer-XXXXXX",
		(void *)&ipc_instance->dispatch_buffer,
		dispatch_size);
	if (sys_res == -1) {
		res = CS_ERR_LIBRARY;
		goto error_dispatch_buffer;
	}

#if _POSIX_THREAD_PROCESS_SHARED > 0
	sem_init (&ipc_instance->control_buffer->sem_request_or_flush_or_exit, 1, 0);
	sem_init (&ipc_instance->control_buffer->sem_request, 1, 0);
	sem_init (&ipc_instance->control_buffer->sem_response, 1, 0);
	sem_init (&ipc_instance->control_buffer->sem_dispatch, 1, 0);
#else
{
	int i;

	/*
	 * Allocate a semaphore segment
	 */
	while (1) {
		semkey = random();
		ipc_instance->euid = geteuid ();
		if ((ipc_instance->control_buffer->semid
		     = semget (semkey, 4, IPC_CREAT|IPC_EXCL|0600)) != -1) {
		      break;
		}
		/*
		 * EACCESS can be returned as non root user when opening a different
		 * users semaphore.
		 *
		 * EEXIST can happen when we are a root or nonroot user opening
		 * an existing shared memory segment for which we have access
		 */
		if (errno != EEXIST && errno != EACCES) {
			res = CS_ERR_LIBRARY;
			goto error_exit;
		}
	}

	for (i = 0; i < 4; i++) {
		semun.val = 0;
		sys_res = semctl (ipc_instance->control_buffer->semid, i, SETVAL, semun);
		if (sys_res != 0) {
			res = CS_ERR_LIBRARY;
			goto error_exit;
		}
	}
}
#endif

	/*
	 * Initialize IPC setup message
	 */
	req_setup.service = service;
	strcpy (req_setup.control_file, control_map_path);
	strcpy (req_setup.request_file, request_map_path);
	strcpy (req_setup.response_file, response_map_path);
	strcpy (req_setup.dispatch_file, dispatch_map_path);
	req_setup.control_size = 8192;
	req_setup.request_size = request_size;
	req_setup.response_size = response_size;
	req_setup.dispatch_size = dispatch_size;

#if _POSIX_THREAD_PROCESS_SHARED < 1
	req_setup.semkey = semkey;
#endif

	res = socket_send (request_fd, &req_setup, sizeof (mar_req_setup_t));
	if (res != CS_OK) {
		goto error_exit;
	}
	res = socket_recv (request_fd, &res_setup, sizeof (mar_res_setup_t));
	if (res != CS_OK) {
		goto error_exit;
	}

	ipc_instance->fd = request_fd;

	if (res_setup.error == CS_ERR_TRY_AGAIN) {
		res = res_setup.error;
		goto error_exit;
	}

	ipc_instance->control_size = 8192;
	ipc_instance->request_size = request_size;
	ipc_instance->response_size = response_size;
	ipc_instance->dispatch_size = dispatch_size;

	pthread_mutex_init (&ipc_instance->mutex, NULL);

	hdb_handle_put (&ipc_hdb, *handle);

	return (res_setup.error);

error_exit:
#if _POSIX_THREAD_PROCESS_SHARED < 1
	if (ipc_instance->control_buffer->semid > 0)
		semctl (ipc_instance->control_buffer->semid, 0, IPC_RMID);
#endif
	memory_unmap (ipc_instance->dispatch_buffer, dispatch_size);
error_dispatch_buffer:
	memory_unmap (ipc_instance->response_buffer, response_size);
error_response_buffer:
	memory_unmap (ipc_instance->request_buffer, request_size);
error_request_buffer:
	memory_unmap (ipc_instance->control_buffer, 8192);
error_connect:
	close (request_fd);

	hdb_handle_destroy (&ipc_hdb, *handle);
	hdb_handle_put (&ipc_hdb, *handle);

	return (res);
}
Ejemplo n.º 21
0
void OS::start(uint32_t boot_magic, uint32_t boot_addr) {

  atexit(default_exit);
  default_stdout_handlers();

  // Print a fancy header
  FILLINE('=');
  CAPTION("#include<os> // Literally\n");
  FILLINE('=');

  auto esp = get_cpu_esp();
  MYINFO ("Stack: 0x%x", esp);
  Expects (esp < 0xA0000 and esp > 0x0 and "Stack location OK");

  MYINFO("Boot args: 0x%x (multiboot magic), 0x%x (bootinfo addr)",
         boot_magic, boot_addr);

  MYINFO("Max mem (from linker): %i MiB", reinterpret_cast<size_t>(&_MAX_MEM_MIB_));

  if (boot_magic == MULTIBOOT_BOOTLOADER_MAGIC) {
    OS::multiboot(boot_magic, boot_addr);
  } else {

    // Fetch CMOS memory info (unfortunately this is maximally 10^16 kb)
    auto mem = cmos::meminfo();
    low_memory_size_ = mem.base.total * 1024;
    INFO2("* Low memory: %i Kib", mem.base.total);
    high_memory_size_ = mem.extended.total * 1024;

    // Use memsize provided by Make / linker unless CMOS knows this is wrong
    decltype(high_memory_size_) hardcoded_mem = reinterpret_cast<size_t>(&_MAX_MEM_MIB_ - 0x100000) << 20;
    if (mem.extended.total == 0xffff or hardcoded_mem < mem.extended.total) {
      high_memory_size_ = hardcoded_mem;
      INFO2("* High memory (from linker): %i Kib", high_memory_size_ / 1024);
    } else {
      INFO2("* High memory (from cmos): %i Kib", mem.extended.total);
    }
  }

  MYINFO("Assigning fixed memory ranges (Memory map)");
  auto& memmap = memory_map();

  // @ Todo: The first ~600k of memory is free for use. What can we put there?
  memmap.assign_range({0x0009FC00, 0x0009FFFF,
        "EBDA", "Extended BIOS data area"});
  memmap.assign_range({0x000A0000, 0x000FFFFF,
        "VGA/ROM", "Memory mapped video memory"});
  memmap.assign_range({(uintptr_t)&_LOAD_START_, (uintptr_t)&_end,
        "ELF", "Your service binary including OS"});

  // @note for security we don't want to expose this
  memmap.assign_range({(uintptr_t)&_end + 1, heap_begin - 1,
        "Pre-heap", "Heap randomization area (not for use))"});

  memmap.assign_range({0x8000, 0x9fff, "Statman", "Statistics"});
  memmap.assign_range({0xA000, 0x9fbff, "Kernel / service main stack"});

  // Create ranges for heap and the remaining address space
  // @note : since the maximum size of a span is unsigned (ptrdiff_t) we may need more than one
  uintptr_t addr_max = std::numeric_limits<std::size_t>::max();
  uintptr_t span_max = std::numeric_limits<std::ptrdiff_t>::max();

  // Give the rest of physical memory to heap
  heap_max_ = ((0x100000 + high_memory_size_)  & 0xffff0000) - 1;

  // ...Unless it's more than the maximum for a range
  // @note : this is a stupid way to limit the heap - we'll change it, but not until
  // we have a good solution.
  heap_max_ = std::min(span_max, heap_max_);

  memmap.assign_range({heap_begin, heap_max_,
        "Heap", "Dynamic memory", heap_usage });

  uintptr_t unavail_start = 0x100000 + high_memory_size_;
  size_t interval = std::min(span_max, addr_max - unavail_start) - 1;
  uintptr_t unavail_end = unavail_start + interval;

  while (unavail_end < addr_max){
    INFO2("* Unavailable memory: 0x%x - 0x%x", unavail_start, unavail_end);
    memmap.assign_range({unavail_start, unavail_end,
          "N/A", "Reserved / outside physical range" });
    unavail_start = unavail_end + 1;
    interval = std::min(span_max, addr_max - unavail_start);
    // Increment might wrapped around
    if (unavail_start > unavail_end + interval or unavail_start + interval == addr_max){
      INFO2("* Last chunk of memory: 0x%x - 0x%x", unavail_start, addr_max);
      memmap.assign_range({unavail_start, addr_max,
            "N/A", "Reserved / outside physical range" });
      break;
    }

    unavail_end += interval;
  }


  MYINFO("Printing memory map");

  for (const auto &i : memory_map())
    INFO2("* %s",i.second.to_string().c_str());

  // Set up interrupt and exception handlers
  IRQ_manager::init();

  // read ACPI tables
  hw::ACPI::init();

  // setup APIC, APIC timer, SMP etc.
  hw::APIC::init();

  // enable interrupts
  INFO("BSP", "Enabling interrupts");
  IRQ_manager::enable_interrupts();

  // Initialize the Interval Timer
  hw::PIT::init();

  // Initialize PCI devices
  PCI_manager::init();

  // Print registered devices
  hw::Devices::print_devices();

  // Estimate CPU frequency
  MYINFO("Estimating CPU-frequency");
  INFO2("|");
  INFO2("+--(10 samples, %f sec. interval)",
        (hw::PIT::frequency() / _cpu_sampling_freq_divider_).count());
  INFO2("|");

  // TODO: Debug why actual measurments sometimes causes problems. Issue #246.
  cpu_mhz_ = hw::PIT::CPU_frequency();
  INFO2("+--> %f MHz", cpu_mhz_.count());

  // cpu_mhz must be known before we can start timer system
  /// initialize timers hooked up to APIC timer
  Timers::init(
    // timer start function
    hw::APIC_Timer::oneshot,
    // timer stop function
    hw::APIC_Timer::stop);

  // initialize BSP APIC timer
  hw::APIC_Timer::init(
  [] {
    // set final interrupt handler
    hw::APIC_Timer::set_handler(Timers::timers_handler);
    // signal that kernel is done with everything
    Service::ready();
    // signal ready
    // NOTE: this executes the first timers, so we
    // don't want to run this before calling Service ready
    Timers::ready();
  });

  // Realtime/monotonic clock
  RTC::init();
  booted_at_ = RTC::now();

  // sleep statistics
  os_cycles_hlt = &Statman::get().create(
      Stat::UINT64, std::string("cpu0.cycles_hlt")).get_uint64();
  os_cycles_total = &Statman::get().create(
      Stat::UINT64, std::string("cpu0.cycles_total")).get_uint64();

  // Trying custom initialization functions
  MYINFO("Calling custom initialization functions");
  for (auto init : custom_init_) {
    INFO2("* Calling %s", init.name_);
    try{
      init.func_();
    } catch(std::exception& e){
      MYINFO("Exception thrown when calling custom init: %s", e.what());
    } catch(...){
      MYINFO("Unknown exception when calling custom initialization function");
    }
  }
  // Everything is ready
  MYINFO("Starting %s", Service::name().c_str());
  FILLINE('=');
  // initialize random seed based on cycles since start
  srand(cycles_since_boot() & 0xFFFFFFFF);
  // begin service start
  Service::start(Service::command_line());

  event_loop();
}
Ejemplo n.º 22
0
void OS::start(uint32_t boot_magic, uint32_t boot_addr)
{
  OS::cmdline = Service::binary_name();

  // Initialize stdout handlers
  if(os_default_stdout) {
    OS::add_stdout(&OS::default_stdout);
  }

  PROFILE("OS::start");
  // Print a fancy header
  CAPTION("#include<os> // Literally");

  MYINFO("Stack: %p", get_cpu_esp());
  MYINFO("Boot magic: 0x%x, addr: 0x%x", boot_magic, boot_addr);

  // Call global ctors
  PROFILE("Global constructors");
  __libc_init_array();

  // PAGING //
  PROFILE("Enable paging");
  extern void __arch_init_paging();
  __arch_init_paging();

  // BOOT METHOD //
  PROFILE("Multiboot / legacy");
  OS::memory_end_ = 0;
  // Detect memory limits etc. depending on boot type
  if (boot_magic == MULTIBOOT_BOOTLOADER_MAGIC) {
    OS::multiboot(boot_addr);
  } else {

    if (is_softreset_magic(boot_magic) && boot_addr != 0)
        OS::resume_softreset(boot_addr);

    OS::legacy_boot();
  }
  assert(OS::memory_end_ != 0);
  // Give the rest of physical memory to heap
  OS::heap_max_ = OS::memory_end_;

  /// STATMAN ///
  PROFILE("Statman");
  /// initialize on page 9, 8 pages in size
  Statman::get().init(0x8000, 0x8000);

  PROFILE("Memory map");
  // Assign memory ranges used by the kernel
  auto& memmap = memory_map();
  MYINFO("Assigning fixed memory ranges (Memory map)");

  memmap.assign_range({0x8000, 0xffff, "Statman"});
#if defined(ARCH_x86_64)
  /**
   * TODO: Map binary parts using mem::map instead of assigning ranges directly
   * e.g. the .text segment is now mapped individually by __arch_init_paging
   */
  memmap.assign_range({0x1000, 0x6fff, "Pagetables"});
  memmap.assign_range({0x10000, 0x9d3ff, "Stack"});
#elif defined(ARCH_i686)
  memmap.assign_range({0x10000, 0x9d3ff, "Stack"});
#endif

  assert(::heap_begin != 0x0 and OS::heap_max_ != 0x0);
  // @note for security we don't want to expose this
  memmap.assign_range({(uintptr_t)&_end, ::heap_begin - 1,
        "Pre-heap"});

  uintptr_t span_max = std::numeric_limits<std::ptrdiff_t>::max();
  uintptr_t heap_range_max_ = std::min(span_max, OS::heap_max_);

  MYINFO("Assigning heap");
  memmap.assign_range({::heap_begin, heap_range_max_,
        "Dynamic memory", heap_usage });

  MYINFO("Virtual memory map");
  for (const auto &i : memmap)
    INFO2("%s",i.second.to_string().c_str());

  PROFILE("Platform init");
  extern void __platform_init();
  __platform_init();

  PROFILE("RTC init");
  // Realtime/monotonic clock
  RTC::init();
}
Ejemplo n.º 23
0
static void *huge_move_expand(struct thread_cache *cache, void *old_addr, size_t old_size, size_t new_size) {
    struct arena *arena;
    void *new_addr = huge_chunk_alloc(cache, new_size, CHUNK_SIZE, &arena);
    if (unlikely(!new_addr)) {
        return NULL;
    }

    bool gap = true;
    if (unlikely(memory_remap_fixed(old_addr, old_size, new_addr, new_size))) {
        memcpy(new_addr, old_addr, old_size);
        if (purge_ratio >= 0) {
            memory_decommit(old_addr, old_size);
        }
        gap = false;
    } else {
        // Attempt to fill the virtual memory hole. The kernel should provide a flag for preserving
        // the old mapping to avoid the possibility of this failing and creating fragmentation.
        //
        // https://lkml.org/lkml/2014/10/2/624
        void *extra = memory_map(old_addr, old_size, false);
        if (likely(extra)) {
            if (unlikely(extra != old_addr)) {
                memory_unmap(extra, old_size);
            } else {
                gap = false;
            }
        }
    }

    struct extent_node key;
    key.addr = old_addr;

    struct arena *old_arena = get_huge_arena(old_addr);

    extent_tree *huge = acquire_huge(old_arena);
    struct extent_node *node = extent_tree_ad_search(huge, &key);
    assert(node);
    extent_tree_ad_remove(huge, node);
    node->addr = new_addr;
    node->size = new_size;

    if (arena != old_arena) {
        release_huge(old_arena);
        huge = acquire_huge(arena);
    }

    extent_tree_ad_insert(huge, node);
    release_huge(arena);

    if (!gap) {
        if (arena != old_arena && old_arena) {
            mutex_lock(&old_arena->mutex);
        }
        chunk_free(get_recycler(old_arena), old_addr, old_size);
        if (arena != old_arena && old_arena) {
            mutex_unlock(&old_arena->mutex);
        }
    }

    maybe_unlock_arena(arena);
    return new_addr;
}
Ejemplo n.º 24
0
int coroipcs_handler_dispatch (
	int fd,
	int revent,
	void *context)
{
	mar_req_setup_t *req_setup;
	struct conn_info *conn_info = (struct conn_info *)context;
	int res;
	char buf = 0;

	if (ipc_thread_exiting (conn_info)) {
		return conn_info_destroy (conn_info);
	}

	/*
	 * If an error occurs, request exit
	 */
	if (revent & (POLLERR|POLLHUP)) {
		ipc_disconnect (conn_info);
		return (0);
	}

	/*
	 * Read the header and process it
	 */
	if (conn_info->service == SOCKET_SERVICE_INIT && (revent & POLLIN)) {
		pthread_attr_t thread_attr;

		/*
		 * Receive in a nonblocking fashion the request
		 * IF security invalid, send ERR_SECURITY, otherwise
		 * send OK
		 */
		res = req_setup_recv (conn_info);
		if (res != CS_OK && res != CS_ERR_LIBRARY) {
			req_setup_send (conn_info, res);
		}
		if (res != CS_OK) {
			return (0);
		}

		pthread_mutex_init (&conn_info->mutex, NULL);
		req_setup = (mar_req_setup_t *)conn_info->setup_msg;
		/*
		 * Is the service registered ?
		 * Has service init function ?
		 */
		if (api->service_available (req_setup->service) == 0 ||
		    api->init_fn_get (req_setup->service) == NULL) {
			req_setup_send (conn_info, CS_ERR_NOT_EXIST);
			ipc_disconnect (conn_info);
			return (0);
		}
#if _POSIX_THREAD_PROCESS_SHARED < 1
		conn_info->semkey = req_setup->semkey;
#endif
		res = memory_map (
			req_setup->control_file,
			req_setup->control_size,
			(void *)&conn_info->control_buffer);
		if (res == -1) {
			goto send_setup_response;
		}
		conn_info->control_size = req_setup->control_size;

		res = memory_map (
			req_setup->request_file,
			req_setup->request_size,
			(void *)&conn_info->request_buffer);
		if (res == -1) {
			goto send_setup_response;
		}
		conn_info->request_size = req_setup->request_size;

		res = memory_map (
			req_setup->response_file,
			req_setup->response_size,
			(void *)&conn_info->response_buffer);
		if (res == -1) {
			goto send_setup_response;
		}
		conn_info->response_size = req_setup->response_size;

		res = circular_memory_map (
			req_setup->dispatch_file,
			req_setup->dispatch_size,
			(void *)&conn_info->dispatch_buffer);
		if (res == -1) {
			goto send_setup_response;
		}
		conn_info->dispatch_size = req_setup->dispatch_size;

 send_setup_response:
		if (res == 0) {
			req_setup_send (conn_info, CS_OK);
		} else {
			req_setup_send (conn_info, CS_ERR_LIBRARY);
			ipc_disconnect (conn_info);
			return (0);
		}

		conn_info->service = req_setup->service;
		conn_info->refcount = 0;
		conn_info->setup_bytes_read = 0;

#if _POSIX_THREAD_PROCESS_SHARED < 1
		conn_info->control_buffer->semid = semget (conn_info->semkey, 3, 0600);
#endif
		conn_info->pending_semops = 0;

		/*
		 * ipc thread is the only reference at startup
		 */
		conn_info->refcount = 1;
		conn_info->state = CONN_STATE_THREAD_ACTIVE;

		conn_info->private_data = api->malloc (api->private_data_size_get (conn_info->service));
		memset (conn_info->private_data, 0,
			api->private_data_size_get (conn_info->service));

		api->init_fn_get (conn_info->service) (conn_info);

		/* create stats objects */
		coroipcs_init_conn_stats (conn_info);

		pthread_attr_init (&thread_attr);
		/*
		* IA64 needs more stack space then other arches
		*/
		#if defined(__ia64__)
		pthread_attr_setstacksize (&thread_attr, 400000);
		#else
		pthread_attr_setstacksize (&thread_attr, 200000);
		#endif

		pthread_attr_setdetachstate (&thread_attr, PTHREAD_CREATE_JOINABLE);
		res = pthread_create (&conn_info->thread,
			&thread_attr,
			pthread_ipc_consumer,
			conn_info);
		pthread_attr_destroy (&thread_attr);

		/*
		 * Security check - disallow multiple configurations of
		 * the ipc connection
		 */
		if (conn_info->service == SOCKET_SERVICE_INIT) {
			conn_info->service = SOCKET_SERVICE_SECURITY_VIOLATION;
		}
	} else
	if (revent & POLLIN) {
		coroipcs_refcount_inc (conn_info);
		res = recv (fd, &buf, 1, MSG_NOSIGNAL);
		if (res == 1) {
			switch (buf) {
			case MESSAGE_REQ_CHANGE_EUID:
				if (priv_change (conn_info) == -1) {
					ipc_disconnect (conn_info);
				}
				break;
			default:
				res = 0;
				break;
			}
		}
#if defined(COROSYNC_SOLARIS) || defined(COROSYNC_BSD) || defined(COROSYNC_DARWIN)
		/* On many OS poll never return POLLHUP or POLLERR.
		 * EOF is detected when recvmsg return 0.
		 */
		if (res == 0) {
			ipc_disconnect (conn_info);
			coroipcs_refcount_dec (conn_info);
			return (0);
		}
#endif
		coroipcs_refcount_dec (conn_info);
	}

	if (revent & POLLOUT) {
		int psop = conn_info->pending_semops;
		int i;

		assert (psop != 0);
		for (i = 0; i < psop; i++) {
			res = send (conn_info->fd, &buf, 1, MSG_NOSIGNAL);
			if (res != 1) {
				return (0);
			} else {
				conn_info->pending_semops -= 1;
			}
		}
		if (conn_info->poll_state == POLL_STATE_INOUT) {
			conn_info->poll_state = POLL_STATE_IN;
			api->poll_dispatch_modify (conn_info->fd, POLLIN|POLLNVAL);
		}
	}

	return (0);
}