summaryrefslogtreecommitdiffstats
path: root/pk/kernel/pk_init.c
blob: 2ac06f337bf8f4184105c80abe7bfd43289354e3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
//-----------------------------------------------------------------------------
// *! (C) Copyright International Business Machines Corp. 2014
// *! All Rights Reserved -- Property of IBM
// *! *** IBM Confidential ***
//-----------------------------------------------------------------------------

/// \file pk_init.c
/// \brief PK initialization
///
/// The entry points in this file are initialization routines - they are never
/// needed after PK initialization and their code space could be reclaimed by
/// the application after initialization if required.

#include "pk.h"
#include "pk_trace.h"

uint32_t __pk_timebase_frequency_hz;
uint32_t __pk_timebase_frequency_khz;
uint32_t __pk_timebase_frequency_mhz;

/// Initialize PK.  
///
/// \param noncritical_stack A stack area for noncritical interrupt handlers.
///
/// \param noncritical_stack_size The size (in bytes) of the stack area for
/// noncritical interrupt handlers. 
///
/// \param critical_stack A stack area for critical interrupt handlers.
///
/// \param critical_stack_size The size (in bytes) of the stack area for
/// critical interrupt handlers. 
///
/// \param initial_timebase The initial value of the PK timebase.  If this
/// argument is given as the special value \c PK_TIMEBASE_CONTINUE, then the
/// timebase is not reset.
///
/// \param timebase_frequency_hz The frequency of the PK timebase in Hz.
///
/// This routine \e must be called before any other PK / routines, and \e
/// should be called before any interrupts are enabled.
///
/// Return values other than PK_OK (0) are errors; see \ref pk_errors
///
/// \retval 0 Successful completion
///
/// \retval -PK_INVALID_ARGUMENT_INIT A stack pointer is 0 or is given 
/// a 0 size.
///
/// \retval -PK_STACK_OVERFLOW One or both stacks are not large enough to
/// support a minimum context save in the event of an interrupt.

// Note that PK does not rely on any static initialization of dynamic
// variables. In debugging sessions using RAM-resident PK images it is
// assumed that the processor may be reset at any time, so we always need to
// reset everything at initialization.

int
pk_initialize(PkAddress  noncritical_stack,
               size_t      noncritical_stack_size,
               PkTimebase initial_timebase,
               uint32_t    timebase_frequency_hz)
{
    int rc;

    if (PK_ERROR_CHECK_API) {
        PK_ERROR_IF((noncritical_stack == 0) ||
                     (noncritical_stack_size == 0),
                     PK_INVALID_ARGUMENT_INIT);
    }

    __pk_timebase_frequency_hz = timebase_frequency_hz;
    __pk_timebase_frequency_khz = timebase_frequency_hz / 1000;
    __pk_timebase_frequency_mhz = timebase_frequency_hz / 1000000;

    __pk_thread_machine_context_default = PK_THREAD_MACHINE_CONTEXT_DEFAULT;

    rc = __pk_stack_init(&noncritical_stack, &noncritical_stack_size);
    if (rc) {
        return rc;
    }

    __pk_noncritical_stack = noncritical_stack;
    __pk_noncritical_stack_size = noncritical_stack_size;

#if PK_TIMER_SUPPORT

    // Initialize the time queue sentinel as a circular queue, set the next
    // timeout and clear the cursor.

    pk_deque_sentinel_create((PkDeque*)&__pk_time_queue);
    __pk_time_queue.cursor = 0;
    __pk_time_queue.next_timeout = PK_TIMEBASE_MAX;

#if PK_TRACE_SUPPORT
extern PkTimer       g_pk_trace_timer;
extern PkTraceBuffer g_pk_trace_buf;

    // Schedule the timer that puts a 64bit timestamp in the trace buffer
    // periodically.  This allows us to use 32bit timestamps.
    pk_timer_schedule(&g_pk_trace_timer,
                      PK_TRACE_TIMER_PERIOD,
                      0);

    //set the trace timebase HZ
    g_pk_trace_buf.hz = timebase_frequency_hz;

    //set the timebase ajdustment for trace synchronization
    pk_trace_set_timebase(initial_timebase);

#endif  /* PK_TRACE_SUPPORT */

#endif  /* PK_TIMER_SUPPORT */

#if PK_THREAD_SUPPORT
    
    // Clear the priority map. The final entry [PK_THREADS] is for the idle
    // thread.

    int i;
    for (i = 0; i <= PK_THREADS; i++) {
        __pk_priority_map[i] = 0;
    }

    // Initialize the thread scheduler

    __pk_thread_queue_clear(&__pk_run_queue);
    __pk_current_thread = 0;   
    __pk_next_thread    = 0;
    __pk_delayed_switch = 0;

#endif  /* PK_THREAD_SUPPORT */

   return PK_OK;
}


/// Call the application main()
///
/// __pk_main() is called from the bootloader.  It's only purpose is to
/// provide a place for the PK_MAIN_HOOK to be called before main() is
/// called.

void
__pk_main(int argc, char **argv)
{
    PK_MAIN_HOOK;

    int main(int argc, char **argv);
    main(argc, argv);
}






        
        
        
OpenPOWER on IntegriCloud