<commit_before>/*
** Copyright 2001-2002, <NAME>. All rights reserved.
** Distributed under the terms of the NewOS License.
*/
#include <kernel/kernel.h>
#include <kernel/arch/vm_translation_map.h>
#include <kernel/heap.h>
#include <kernel/int.h>
#include <kernel/smp.h>
#include <kernel/vm.h>
#include <kernel/vm_page.h>
#include <kernel/vm_priv.h>
#include <kernel/arch/cpu.h>
#include <kernel/debug.h>
#include <kernel/lock.h>
#include <kernel/sem.h>
#include <kernel/queue.h>
#include <string.h>
#include <boot/stage2.h>
#include <newos/errors.h>

// 256 MB of iospace
#define IOSPACE_SIZE (256*1024*1024)
// put it 256 MB into kernel space
#define IOSPACE_BASE (KERNEL_BASE + IOSPACE_SIZE)
// 4 MB chunks, to optimize for 4 MB pages
#define IOSPACE_CHUNK_SIZE (4*1024*1024)

// data and structures used to represent physical pages mapped into iospace
typedef struct paddr_chunk_descriptor {
	struct paddr_chunk_descriptor *next_q; // must remain first in structure, queue code uses it
	int ref_count;
	addr va;
} paddr_chunk_desc;

static paddr_chunk_desc *paddr_desc;         // will be one per physical chunk
static paddr_chunk_desc **virtual_pmappings; // will be one ptr per virtual chunk in iospace
static int first_free_vmapping;
static int num_virtual_chunks;
static queue mapped_paddr_lru;
static ptentry *iospace_pgtables = NULL;
static mutex iospace_mutex;
static sem_id iospace_full_sem;

#define PAGE_INVALIDATE_CACHE_SIZE 64

// vm_translation object stuff
typedef struct vm_translation_map_arch_info_struct {
	pdentry *pgdir_virt;
	pdentry *pgdir_phys;
	int num_invalidate_pages;
	addr pages_to_invalidate[PAGE_INVALIDATE_CACHE_SIZE];
} vm_translation_map_arch_info;

static ptentry *page_hole = NULL;
static pdentry *page_hole_pgdir = NULL;
static pdentry *kernel_pgdir_phys = NULL;
static pdentry *kernel_pgdir_virt = NULL;

static vm_translation_map *tmap_list;
static spinlock_t tmap_list_lock;

#define CHATTY_TMAP 0

#define ADDR_SHIFT(x) ((x)>>12)
#define ADDR_REVERSE_SHIFT(x) ((x)<<12)

#define VADDR_TO_PDENT(va) (((va) / PAGE_SIZE) / 1024)
#define VADDR_TO_PTENT(va) (((va) / PAGE_SIZE) % 1024)

#define FIRST_USER_PGDIR_ENT    (VADDR_TO_PDENT(USER_BASE))
#define NUM_USER_PGDIR_ENTS     (VADDR_TO_PDENT(USER_SIZE))
#define FIRST_KERNEL_PGDIR_ENT  (VADDR_TO_PDENT(KERNEL_BASE))
#define NUM_KERNEL_PGDIR_ENTS   (VADDR_TO_PDENT(KERNEL_SIZE))

static int vm_translation_map_quick_query(addr va, addr *out_physical);

static void flush_tmap(vm_translation_map *map);

static void init_pdentry(pdentry *e)
{
	*(int *)e = 0;
}

static void init_ptentry(ptentry *e)
{
	*(int *)e = 0;
}

static void _update_all_pgdirs(int index, pdentry e)
{
	unsigned int state;
	vm_translation_map *entry;

	state = int_disable_interrupts();
	acquire_spinlock(&tmap_list_lock);

	for(entry = tmap_list; entry != NULL; entry = entry->next)
		entry->arch_data->pgdir_virt[index] = e;
<commit_msg>fix a subtle bug in the x86 translation map code where it didn't quite clear all of the entries of a new pagedir (missed the last user mode one), which probably caused some subtle crashers.<commit_after>/*
** Copyright 2001-2002, <NAME>. All rights reserved.
** Distributed under the terms of the NewOS License.
*/
#include <kernel/kernel.h>
#include <kernel/arch/vm_translation_map.h>
#include <kernel/heap.h>
#include <kernel/int.h>
#include <kernel/smp.h>
#include <kernel/vm.h>
#include <kernel/vm_page.h>
#include <kernel/vm_priv.h>
#include <kernel/arch/cpu.h>
#include <kernel/debug.h>
#include <kernel/lock.h>
#include <kernel/sem.h>
#include <kernel/queue.h>
#include <string.h>
#include <boot/stage2.h>
#include <newos/errors.h>

// 256 MB of iospace
#define IOSPACE_SIZE (256*1024*1024)
// put it 256 MB into kernel space
#define IOSPACE_BASE (KERNEL_BASE + IOSPACE_SIZE)
// 4 MB chunks, to optimize for 4 MB pages
#define IOSPACE_CHUNK_SIZE (4*1024*1024)

// data and structures used to represent physical pages mapped into iospace
typedef struct paddr_chunk_descriptor {
	struct paddr_chunk_descriptor *next_q; // must remain first in structure, queue code uses it
	int ref_count;
	addr va;
} paddr_chunk_desc;

static paddr_chunk_desc *paddr_desc;         // will be one per physical chunk
static paddr_chunk_desc **virtual_pmappings; // will be one ptr per virtual chunk in iospace
static int first_free_vmapping;
static int num_virtual_chunks;
static queue mapped_paddr_lru;
static ptentry *iospace_pgtables = NULL;
static mutex iospace_mutex;
static sem_id iospace_full_sem;

#define PAGE_INVALIDATE_CACHE_SIZE 64

// vm_translation object stuff
typedef struct vm_translation_map_arch_info_struct {
	pdentry *pgdir_virt;
	pdentry *pgdir_phys;
	int num_invalidate_pages;
	addr pages_to_invalidate[PAGE_INVALIDATE_CACHE_SIZE];
} vm_translation_map_arch_info;

static ptentry *page_hole = NULL;
static pdentry *page_hole_pgdir = NULL;
static pdentry *kernel_pgdir_phys = NULL;
static pdentry *kernel_pgdir_virt = NULL;

static vm_translation_map *tmap_list;
static spinlock_t tmap_list_lock;

#define CHATTY_TMAP 0

#define ADDR_SHIFT(x) ((x)>>12)
#define ADDR_REVERSE_SHIFT(x) ((x)<<12)

#define VADDR_TO_PDENT(va) (((va) / PAGE_SIZE) / 1024)
#define VADDR_TO_PTENT(va) (((va) / PAGE_SIZE) % 1024)

#define FIRST_USER_PGDIR_ENT    (VADDR_TO_PDENT(USER_BASE))
#define NUM_USER_PGDIR_ENTS     (VADDR_TO_PDENT(ROUNDUP(USER_SIZE, PAGE_SIZE * 1024)))
#define FIRST_KERNEL_PGDIR_ENT  (VADDR_TO_PDENT(KERNEL_BASE))
#define NUM_KERNEL_PGDIR_ENTS   (VADDR_TO_PDENT(KERNEL_SIZE))

static int vm_translation_map_quick_query(addr va, addr *out_physical);

static void flush_tmap(vm_translation_map *map);

static void init_pdentry(pdentry *e)
{
	*(int *)e = 0;
}

static void init_ptentry(ptentry *e)
{
	*(int *)e = 0;
}

static void _update_all_pgdirs(int index, pdentry e)
{
	unsigned int state;
	vm_translation_map *entry;

	state = int_disable_interrupts();
	acquire_spinlock(&tmap_list_lock);

	for(entry = tmap_list; entry != NULL; entry = entry->next)
		entry->arch_data->pgdir_virt[index] = e;

{'fraction_non_alphanumeric': 0.10238055601797902, 'fraction_numerical': 0.018977859164308306, 'mean_word_length': 5.913693901035673, 'pattern_counts': {'":': 0, '<': 41, '<?xml version=': 0, '>': 47, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3005732', 'n_tokens_mistral': 2283, 'n_tokens_neox': 2165, 'n_words': 566}