<commit_before>/*
 * The MIT License (MIT)
 * Copyright (c) 2015 <NAME> <<EMAIL>>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal in 
 * the Software without restriction, including without limitation the rights to use, copy, 
 * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, 
 * and to permit persons to whom the Software is furnished to do so, subject to the 
 * following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all copies 
 * or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS 
 * OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * task.c
 *  Created on: Dec 23, 2015
 *      Author: <NAME>
 *  Contents: task management
 */

#include "task.h"

array_t* cpus;
extern volatile uintmax_t clock_ms;
extern volatile uintmax_t clock_s;
uint32_t cpuid_to_cputord[256];
uint32_t apicaddr;

void ap_main(uint64_t proc_id){
	cpu_t* cpu = (cpu_t*)array_get_at(cpus, cpuid_to_cputord[proc_id]);
	cpu->started = true;

	bool ddebug = true;
	while (ddebug) ;

	while (true) ;
}

void send_ipi_to(uint8_t apic_id, uint8_t vector) {
	while(*(uint32_t*)physical_to_virtual((apicaddr + 0x30) & (1<<12)))
    	;

    uint32_t sendvalue = ((uint32_t)apic_id) << 24;
    *((uint32_t*)physical_to_virtual(apicaddr + 0x31 * 0x10))=sendvalue;

    uint32_t control = vector;

    /* required to be set for non-INIT IPIs */
    control |= 1<<14;

    /* otherwise, everything's good: IPI mode, fixed delivery vector,
        only to the specified APIC, edge-triggered. */
    sendvalue = control;
    *((uint32_t*)physical_to_virtual(apicaddr + 0x30 * 0x10))=sendvalue;
}

extern void* Gdt32;

void initialize_mp(unsigned int localcpu){
	uint32_t proclen = array_get_size(cpus);
	uintmax_t clock_data;
	uintmax_t clock_sdata;

	for (uint32_t i=0; i<proclen; i++){
		cpu_t* cpu = array_get_at(cpus, i);
		if (cpu->apic_id == localcpu){
			cpu->started = true;
			continue;
		}
		vlog_msg("Attempting to initialize logical cpu %llu, apic %hhx.", cpu->processor_id, cpu->apic_id);

		// INIT IPI
		DISABLE_INTERRUPTS();
		uint32_t sendvalue = ((uint32_t)cpu->apic_id) << 24;
		*((uint32_t*)physical_to_virtual(apicaddr + 0x31 * 0x10))=sendvalue;
		sendvalue = 5 << 7;
		*((uint32_t*)physical_to_virtual(apicaddr + 0x30 * 0x10))=sendvalue;
		ENABLE_INTERRUPTS();
	}

	clock_data = clock_ms+10;
	clock_sdata = clock_s;
	while (clock_data <= clock_ms && clock_sdata != clock_s) ;

	for (uint32_t i=0; i<proclen; i++){
		cpu_t* cpu = array_get_at(cpus, i);
		if (cpu->apic_id == localcpu){
			cpu->started = true;
			continue;
		}

		vlog_msg("SIPI cpu %llu, apic %hhx.", cpu->processor_id, cpu->apic_id);

		// SIPI
		DISABLE_INTERRUPTS();
		uint32_t sendvalue = ((uint32_t)cpu->apic_id) << 24;
		*((uint32_t*)physical_to_virtual(apicaddr + 0x31 * 0x10))=sendvalue;
		sendvalue = (6 << 7) | 2;
		*((uint32_t*)physical_to_virtual(apicaddr + 0x30 * 0x10))=sendvalue;
		ENABLE_INTERRUPTS();
		vlog_msg("Attempted to initialize logical cpu %llu, apic %hhx", cpu->processor_id, cpu->apic_id);
	}

	clock_data = clock_ms+200;
	clock_sdata = clock_s;
	while (clock_data <= clock_ms && clock_sdata != clock_s) ;

	bool initialized = true;
	for (uint32_t i=0; i<proclen; i++){
		cpu_t* cpu = array_get_at(cpus, i);
		if (!cpu->started){
			initialized = false;
			break;
		}
	}

	if (!initialized){
		for (uint32_t i=0; i<proclen; i++){
			cpu_t* cpu = array_get_at(cpus, i);
			if (cpu->apic_id == localcpu){
				continue;
			}
			// Second SIPI
			DISABLE_INTERRUPTS();
			uint32_t sendvalue = ((uint32_t)cpu->apic_id) << 24;
			*((uint32_t*)physical_to_virtual(apicaddr + 0x31 * 0x10))=sendvalue;
			sendvalue = (6 << 7) | 2;
			*((uint32_t*)physical_to_virtual(apicaddr + 0x30 * 0x10))=sendvalue;
			ENABLE_INTERRUPTS();
		}
	}
}

cpu_t* make_cpu(MADT_LOCAL_APIC* apic) {
	cpu_t* cpu = malloc(sizeof(cpu_t));
	if (cpu == NULL)
		error(ERROR_MINIMAL_MEMORY_FAILURE, 0, 0, &make_cpu);
	cpu->processor_id = apic->processor_id;
	cpu->apic_id = apic->id;
	cpu->started = false;
	cpu->processes = create_array();
	cpu->stack = (void*) (((uintptr_t)malloc(0x2000))+0x2000);
	if (cpu->processes == NULL)
		error(ERROR_MINIMAL_MEMORY_FAILURE, 0, 0, &make_cpu);
	return cpu;
}

cpu_t* make_cpu_default() {
	cpu_t* cpu = malloc(sizeof(cpu_t));
	if (cpu == NULL)<commit_msg>more fixes for smp<commit_after>/*
 * The MIT License (MIT)
 * Copyright (c) 2015 <NAME> <<EMAIL>>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal in 
 * the Software without restriction, including without limitation the rights to use, copy, 
 * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, 
 * and to permit persons to whom the Software is furnished to do so, subject to the 
 * following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all copies 
 * or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS 
 * OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * task.c
 *  Created on: Dec 23, 2015
 *      Author: <NAME>
 *  Contents: task management
 */

#include "task.h"

array_t* cpus;
extern volatile uintmax_t clock_ms;
extern volatile uintmax_t clock_s;
uint32_t cpuid_to_cputord[256];
uint32_t apicaddr;

void ap_main(uint64_t proc_id){
	cpu_t* cpu = (cpu_t*)array_get_at(cpus, cpuid_to_cputord[proc_id]);
	cpu->started = true;

	bool ddebug = true;
	while (ddebug) ;

	while (true) ;
}

void send_ipi_to(uint8_t apic_id, uint8_t vector) {
	while((*(uint32_t*)physical_to_virtual((apicaddr + 0x30))) & (1<<12))
		;

    uint32_t sendvalue = ((uint32_t)apic_id) << 24;
    *((uint32_t*)physical_to_virtual(apicaddr + 0x31 * 0x10))=sendvalue;

    uint32_t control = vector;

    /* required to be set for non-INIT IPIs */
    control |= 1<<14;

    /* otherwise, everything's good: IPI mode, fixed delivery vector,
        only to the specified APIC, edge-triggered. */
    sendvalue = control;
    *((uint32_t*)physical_to_virtual(apicaddr + 0x30 * 0x10))=sendvalue;
}

extern void* Gdt32;

void initialize_mp(unsigned int localcpu){
	uint32_t proclen = array_get_size(cpus);
	uintmax_t clock_data;
	uintmax_t clock_sdata;

	for (uint32_t i=0; i<proclen; i++){
		cpu_t* cpu = array_get_at(cpus, i);
		if (cpu->apic_id == localcpu){
			cpu->started = true;
			continue;
		}
		vlog_msg("Attempting to initialize logical cpu %llu, apic %hhx.", cpu->processor_id, cpu->apic_id);

		// INIT IPI
		while((*(uint32_t*)physical_to_virtual((apicaddr + 0x30))) & (1<<12))
			;
		uint32_t sendvalue = ((uint32_t)cpu->apic_id) << 24;
		*((uint32_t*)physical_to_virtual(apicaddr + 0x31 * 0x10))=sendvalue;
		sendvalue = 5 << 7;
		*((uint32_t*)physical_to_virtual(apicaddr + 0x30 * 0x10))=sendvalue;
	}

	clock_data = clock_ms+10;
	clock_sdata = clock_s;
	while (clock_data <= clock_ms && clock_sdata != clock_s) ;

	for (uint32_t i=0; i<proclen; i++){
		cpu_t* cpu = array_get_at(cpus, i);
		if (cpu->apic_id == localcpu){
			cpu->started = true;
			continue;
		}

		while((*(uint32_t*)physical_to_virtual((apicaddr + 0x30))) & (1<<12))
			;

		vlog_msg("SIPI cpu %llu, apic %hhx.", cpu->processor_id, cpu->apic_id);

		// SIPI
		uint32_t sendvalue = ((uint32_t)cpu->apic_id) << 24;
		*((uint32_t*)physical_to_virtual(apicaddr + 0x31 * 0x10))=sendvalue;
		sendvalue = (6 << 7) | 2;
		*((uint32_t*)physical_to_virtual(apicaddr + 0x30 * 0x10))=sendvalue;
		vlog_msg("Attempted to initialize logical cpu %llu, apic %hhx", cpu->processor_id, cpu->apic_id);
	}

	clock_data = clock_ms+200;
	clock_sdata = clock_s;
	while (clock_data <= clock_ms && clock_sdata != clock_s) ;

	bool initialized = true;
	for (uint32_t i=0; i<proclen; i++){
		cpu_t* cpu = array_get_at(cpus, i);
		if (!cpu->started){
			initialized = false;
			break;
		}
	}

	if (!initialized){
		for (uint32_t i=0; i<proclen; i++){
			cpu_t* cpu = array_get_at(cpus, i);
			if (cpu->apic_id == localcpu){
				continue;
			}
			// Second SIPI
			while((*(uint32_t*)physical_to_virtual((apicaddr + 0x30))) & (1<<12))
				;
			uint32_t sendvalue = ((uint32_t)cpu->apic_id) << 24;
			*((uint32_t*)physical_to_virtual(apicaddr + 0x31 * 0x10))=sendvalue;
			sendvalue = (6 << 7) | 2;
			*((uint32_t*)physical_to_virtual(apicaddr + 0x30 * 0x10))=sendvalue;
		}
	}
}

cpu_t* make_cpu(MADT_LOCAL_APIC* apic) {
	cpu_t* cpu = malloc(sizeof(cpu_t));
	if (cpu == NULL)
		error(ERROR_MINIMAL_MEMORY_FAILURE, 0, 0, &make_cpu);
	cpu->processor_id = apic->processor_id;
	cpu->apic_id = apic->id;
	cpu->started = false;
	cpu->processes = create_array();
	cpu->stack = (void*) (((uintptr_t)malloc(0x2000))+0x2000);
	if (cpu->processes == NULL)
		error(ERROR_MINIMAL_MEMORY_FAILURE, 0, 0, &make_cpu);
	return cpu;
}

cpu_t* make_cpu_default() {
	cpu_t* cpu = malloc(sizeof(cpu_t));
	if (cpu == NULL)
{'fraction_non_alphanumeric': 0.13340795766765035, 'fraction_numerical': 0.0360232013839422, 'mean_word_length': 4.385205479452055, 'pattern_counts': {'":': 0, '<': 65, '<?xml version=': 0, '>': 59, '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': '1170104', 'n_tokens_mistral': 4142, 'n_tokens_neox': 3626, 'n_words': 955}