Changeset b366a6f4 in mainline for kernel/arch/sparc64


Ignore:
Timestamp:
2011-06-24T15:58:01Z (14 years ago)
Author:
Martin Decky <martin@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
7250d2c
Parents:
ee2fa30a
Message:

automatic kernel console lockout

  • kernel automatically relinquishes the access to the kernel console when the uspace maps the respective physical memory area
  • kernel output before uspace initialization is currently broken on Ski (no physical memory area), but this is pending further unification
  • kernel console devices are now independent (there is no system-wide "silent" variable), thus on multiple devices the kernel console and uspace output might be usable at the same time
Location:
kernel/arch/sparc64
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • kernel/arch/sparc64/include/drivers/sgcn.h

    ree2fa30a rb366a6f4  
    2727 */
    2828
    29 /** @addtogroup sparc64 
     29/** @addtogroup sparc64
    3030 * @{
    3131 */
     
    4040#include <proc/thread.h>
    4141#include <synch/spinlock.h>
     42#include <ddi/ddi.h>
    4243
    4344/* number of bytes in the TOC magic, including the NULL-terminator */
     
    126127        uintptr_t buffer_begin;
    127128       
     129        /** Physical memory area */
     130        parea_t parea;
     131       
    128132        /**
    129133         * Ensure that writing to the buffer and consequent
  • kernel/arch/sparc64/src/drivers/niagara.c

    ree2fa30a rb366a6f4  
    3232/**
    3333 * @file
    34  * @brief       Niagara input/output driver based on hypervisor calls.
     34 * @brief Niagara input/output driver based on hypervisor calls.
    3535 */
    3636
     
    5252#include <genarch/srln/srln.h>
    5353
    54 /* polling interval in miliseconds */
     54/* Polling interval in miliseconds */
    5555#define POLL_INTERVAL  10000
    5656
    57 /* device instance */
     57/* Device instance */
    5858static niagara_instance_t *instance = NULL;
    5959
    60 static void niagara_putchar(outdev_t *, const wchar_t, bool);
    61 
    62 /** character device operations */
     60static void niagara_putchar(outdev_t *, const wchar_t);
     61
     62/** Character device operations */
    6363static outdev_operations_t niagara_ops = {
    6464        .write = niagara_putchar,
     
    6666};
    6767
    68 /*
     68/**
    6969 * The driver uses hypercalls to print characters to the console. Since the
    7070 * hypercall cannot be performed from the userspace, we do this:
    71  * The kernel "little brother" driver (which will be present no matter what the
    72  * DDI architecture is - as we need the kernel part for the kconsole)
     71 *
     72 * The kernel "little brother" driver (which will be present no matter what
     73 * the DDI architecture is -- as we need the kernel part for the kconsole)
    7374 * defines a shared buffer. Kernel walks through the buffer (in the same thread
    7475 * which is used for polling the keyboard) and prints any pending characters
    75  * to the console (using hypercalls). The userspace fb server maps this shared
    76  * buffer to its address space and output operation it does is performed using
    77  * the mapped buffer. The shared buffer definition follows.
    78  */
    79 #define OUTPUT_BUFFER_SIZE      ((PAGE_SIZE) - 2 * 8)
     76 * to the console (using hypercalls).
     77 *
     78 * The userspace fb server maps this shared buffer to its address space and
     79 * output operation it does is performed using the mapped buffer. The shared
     80 * buffer definition follows.
     81 */
     82#define OUTPUT_BUFFER_SIZE  ((PAGE_SIZE) - 2 * 8)
     83
    8084static volatile struct {
    8185        uint64_t read_ptr;
    8286        uint64_t write_ptr;
    8387        char data[OUTPUT_BUFFER_SIZE];
    84 }
    85         __attribute__ ((packed))
    86         __attribute__ ((aligned(PAGE_SIZE)))
    87         output_buffer;
     88} __attribute__ ((packed)) __attribute__ ((aligned(PAGE_SIZE))) output_buffer;
     89
     90static parea_t outbuf_parea;
    8891
    8992/**
    9093 * Analogous to the output_buffer, see the previous definition.
    9194 */
    92 #define INPUT_BUFFER_SIZE       ((PAGE_SIZE) - 2 * 8)
     95#define INPUT_BUFFER_SIZE  ((PAGE_SIZE) - 2 * 8)
     96
    9397static volatile struct {
    9498        uint64_t write_ptr;
    9599        uint64_t read_ptr;
    96100        char data[INPUT_BUFFER_SIZE];
    97 }
    98         __attribute__ ((packed))
    99         __attribute__ ((aligned(PAGE_SIZE)))
    100         input_buffer;
    101 
    102 
    103 /** Writes a single character to the standard output. */
     101} __attribute__ ((packed)) __attribute__ ((aligned(PAGE_SIZE))) input_buffer;
     102
     103static parea_t inbuf_parea;
     104
     105/** Write a single character to the standard output. */
    104106static inline void do_putchar(const char c) {
    105         /* repeat until the buffer is non-full */
    106         while (__hypercall_fast1(CONS_PUTCHAR, c) == HV_EWOULDBLOCK)
    107                 ;
    108 }
    109 
    110 /** Writes a single character to the standard output. */
    111 static void niagara_putchar(outdev_t *dev, const wchar_t ch, bool silent)
    112 {
    113         if (silent)
    114             return;
    115 
    116         do_putchar(ch);
    117         if (ch == '\n')
    118                 do_putchar('\r');
    119 }
    120 
    121 /**
    122  * Function regularly called by the keyboard polling thread. Asks the
    123  * hypervisor whether there is any unread character. If so, it picks it up
    124  * and sends it to the upper layers of HelenOS.
    125  *
    126  * Apart from that, it also checks whether the userspace output driver has
    127  * pushed any characters to the output buffer. If so, it prints them.
    128  */
    129 static void niagara_poll(niagara_instance_t *instance)
    130 {
    131         /* print any pending characters from the shared buffer to the console */
     107        /* Repeat until the buffer is non-full */
     108        while (__hypercall_fast1(CONS_PUTCHAR, c) == HV_EWOULDBLOCK);
     109}
     110
     111/** Write a single character to the standard output. */
     112static void niagara_putchar(outdev_t *dev, const wchar_t ch)
     113{
     114        if ((!outbuf_parea.mapped) || (console_override)) {
     115                do_putchar(ch);
     116                if (ch == '\n')
     117                        do_putchar('\r');
     118        }
     119}
     120
     121/** Poll keyboard and print pending characters.
     122 *
     123 * Ask the hypervisor whether there is any unread character. If so,
     124 * pick it up and send it to the indev layer.
     125 *
     126 * Check whether the userspace output driver has pushed any
     127 * characters to the output buffer and eventually print them.
     128 *
     129 */
     130static void niagara_poll(void)
     131{
     132        /*
     133         * Print any pending characters from the
     134         * shared buffer to the console.
     135         */
     136       
    132137        while (output_buffer.read_ptr != output_buffer.write_ptr) {
    133138                do_putchar(output_buffer.data[output_buffer.read_ptr]);
    134139                output_buffer.read_ptr =
    135                         ((output_buffer.read_ptr) + 1) % OUTPUT_BUFFER_SIZE;
    136         }
    137 
     140                    ((output_buffer.read_ptr) + 1) % OUTPUT_BUFFER_SIZE;
     141        }
     142       
     143        /*
     144         * Read character from keyboard.
     145         */
     146       
    138147        uint64_t c;
    139 
    140         /* read character from keyboard, send it to upper layers of HelenOS */
    141148        if (__hypercall_fast_ret1(0, 0, 0, 0, 0, CONS_GETCHAR, &c) == HV_EOK) {
    142                 if (!silent) {
    143                         /* kconsole active, send the character to kernel */
     149                if ((!inbuf_parea.mapped) || (console_override)) {
     150                        /*
     151                         * Kernel console is active, send
     152                         * the character to kernel.
     153                         */
    144154                        indev_push_character(instance->srlnin, c);
    145155                } else {
    146                         /* kconsole inactive, send the character to uspace driver */
     156                        /*
     157                         * Kernel console is inactive, send
     158                         * the character to uspace driver.
     159                         */
    147160                        input_buffer.data[input_buffer.write_ptr] = (char) c;
    148161                        input_buffer.write_ptr =
    149                                 ((input_buffer.write_ptr) + 1) % INPUT_BUFFER_SIZE;
     162                            ((input_buffer.write_ptr) + 1) % INPUT_BUFFER_SIZE;
    150163                }
    151164        }
    152165}
    153166
    154 /**
    155  * Polling thread function.
    156  */
    157 static void kniagarapoll(void *instance) {
     167/** Polling thread function.
     168 *
     169 */
     170static void kniagarapoll(void *arg) {
    158171        while (true) {
    159                 niagara_poll(instance);
     172                niagara_poll();
    160173                thread_usleep(POLL_INTERVAL);
    161174        }
    162175}
    163176
    164 /**
    165  * Initializes the input/output subsystem so that the Niagara standard
    166  * input/output is used.
     177/** Initialize the input/output subsystem
     178 *
    167179 */
    168180static void niagara_init(void)
     
    172184       
    173185        instance = malloc(sizeof(niagara_instance_t), FRAME_ATOMIC);
    174        
    175         if (instance) {
    176                 instance->thread = thread_create(kniagarapoll, instance, TASK, 0,
    177                         "kniagarapoll", true);
    178                
    179                 if (!instance->thread) {
    180                         free(instance);
    181                         instance = NULL;
    182                         return;
    183                 }
    184         }
    185 
     186        instance->thread = thread_create(kniagarapoll, NULL, TASK, 0,
     187            "kniagarapoll", true);
     188       
     189        if (!instance->thread) {
     190                free(instance);
     191                instance = NULL;
     192                return;
     193        }
     194       
    186195        instance->srlnin = NULL;
    187 
     196       
    188197        output_buffer.read_ptr = 0;
    189198        output_buffer.write_ptr = 0;
    190199        input_buffer.write_ptr = 0;
    191200        input_buffer.read_ptr = 0;
    192 
     201       
    193202        /*
    194203         * Set sysinfos and pareas so that the userspace counterpart of the
    195204         * niagara fb and kbd driver can communicate with kernel using shared
    196205         * buffers.
    197          */
    198 
     206         */
     207       
    199208        sysinfo_set_item_val("fb.kind", NULL, 5);
    200 
     209       
    201210        sysinfo_set_item_val("niagara.outbuf.address", NULL,
    202                 KA2PA(&output_buffer));
     211            KA2PA(&output_buffer));
    203212        sysinfo_set_item_val("niagara.outbuf.size", NULL,
    204                 PAGE_SIZE);
     213            PAGE_SIZE);
    205214        sysinfo_set_item_val("niagara.outbuf.datasize", NULL,
    206                 OUTPUT_BUFFER_SIZE);
    207 
     215            OUTPUT_BUFFER_SIZE);
     216       
    208217        sysinfo_set_item_val("niagara.inbuf.address", NULL,
    209                 KA2PA(&input_buffer));
     218            KA2PA(&input_buffer));
    210219        sysinfo_set_item_val("niagara.inbuf.size", NULL,
    211                 PAGE_SIZE);
     220            PAGE_SIZE);
    212221        sysinfo_set_item_val("niagara.inbuf.datasize", NULL,
    213                 INPUT_BUFFER_SIZE);
    214 
    215         static parea_t outbuf_parea;
     222           INPUT_BUFFER_SIZE);
     223       
    216224        outbuf_parea.pbase = (uintptr_t) (KA2PA(&output_buffer));
    217225        outbuf_parea.frames = 1;
    218226        outbuf_parea.unpriv = false;
     227        outbuf_parea.mapped = false;
    219228        ddi_parea_register(&outbuf_parea);
    220 
    221         static parea_t inbuf_parea;
     229       
    222230        inbuf_parea.pbase = (uintptr_t) (KA2PA(&input_buffer));
    223231        inbuf_parea.frames = 1;
    224232        inbuf_parea.unpriv = false;
     233        inbuf_parea.mapped = false;
    225234        ddi_parea_register(&inbuf_parea);
    226 
     235       
    227236        outdev_t *niagara_dev = malloc(sizeof(outdev_t), FRAME_ATOMIC);
    228237        outdev_initialize("niagara_dev", niagara_dev, &niagara_ops);
     
    230239}
    231240
    232 /**
    233  * A public function which initializes input from the Niagara console.
     241/** Initialize input from the Niagara console.
     242 *
    234243 */
    235244niagara_instance_t *niagarain_init(void)
    236245{
    237246        niagara_init();
    238 
     247       
    239248        if (instance) {
    240249                srln_instance_t *srln_instance = srln_init();
     
    242251                        indev_t *sink = stdin_wire();
    243252                        indev_t *srln = srln_wire(srln_instance, sink);
    244 
    245                         // wire std. input to niagara
     253                       
    246254                        instance->srlnin = srln;
    247255                        thread_ready(instance->thread);
    248256                }
    249257        }
     258       
    250259        return instance;
    251260}
  • kernel/arch/sparc64/src/drivers/sgcn.c

    ree2fa30a rb366a6f4  
    102102#define SGCN_BUFFER_HEADER  (SGCN_BUFFER(sgcn_buffer_header_t, 0))
    103103
    104 static void sgcn_putchar(outdev_t *, const wchar_t, bool);
     104static void sgcn_putchar(outdev_t *, const wchar_t);
    105105
    106106static outdev_operations_t sgcndev_ops = {
     
    111111static sgcn_instance_t *instance = NULL;
    112112
    113 /**
    114  * Set some sysinfo values (SRAM address and SRAM size).
    115  */
    116 static void register_sram(uintptr_t sram_begin_physical)
    117 {
    118         sysinfo_set_item_val("sram.area.size", NULL, MAPPED_AREA_SIZE);
    119         sysinfo_set_item_val("sram.address.physical", NULL,
    120             sram_begin_physical);
    121 }
    122 
    123 /**
    124  * Initializes the starting address of SRAM.
     113/** Initialize the starting address of SRAM.
    125114 *
    126115 * The SRAM starts 0x900000 + C bytes behind the SBBC start in the
     
    129118 * be set to the virtual address which maps to the SRAM physical
    130119 * address.
     120 *
    131121 */
    132122static void init_sram_begin(void)
     
    149139        instance->sram_begin = hw_map(sram_begin_physical, MAPPED_AREA_SIZE);
    150140       
    151         register_sram(sram_begin_physical);
    152 }
    153 
    154 /**
    155  * Function regularly called by the keyboard polling thread. Finds out whether
    156  * there are some unread characters in the input queue. If so, it picks them up
    157  * and sends them to the upper layers of HelenOS.
     141        link_initialize(&instance->parea.link);
     142        instance->parea.pbase = sram_begin_physical;
     143        instance->parea.frames = SIZE2FRAMES(MAPPED_AREA_SIZE);
     144        instance->parea.unpriv = false;
     145        instance->parea.mapped = false;
     146        ddi_parea_register(&instance->parea);
     147       
     148        sysinfo_set_item_val("sram.area.size", NULL, MAPPED_AREA_SIZE);
     149        sysinfo_set_item_val("sram.address.physical", NULL,
     150            sram_begin_physical);
     151}
     152
     153/** Get unread characters from the input queue.
     154 *
     155 * Check for unread characters in the input queue.
     156 *
    158157 */
    159158static void sgcn_poll(sgcn_instance_t *instance)
     
    163162        uint32_t size = end - begin;
    164163       
    165         if (silent)
     164        if ((instance->parea.mapped) && (!console_override))
    166165                return;
    167166       
    168167        spinlock_lock(&instance->input_lock);
    169168       
    170         /* we need pointers to volatile variables */
     169        /* We need pointers to volatile variables */
    171170        volatile char *buf_ptr = (volatile char *)
    172171            SGCN_BUFFER(char, SGCN_BUFFER_HEADER->in_rdptr);
     
    186185}
    187186
    188 /**
    189  * Polling thread function.
     187/** Polling thread function.
     188 *
    190189 */
    191190static void ksgcnpoll(void *instance) {
    192191        while (true) {
    193                 if (!silent)
    194                         sgcn_poll(instance);
    195                
     192                sgcn_poll(instance);
    196193                thread_usleep(POLL_INTERVAL);
    197194        }
    198195}
    199196
    200 /**
    201  * Initializes the starting address of the SGCN buffer.
     197/** Initialize the starting address of the SGCN buffer.
    202198 *
    203199 * The offset of the SGCN buffer within SRAM is obtained from the
    204200 * SRAM table of contents. The table of contents contains
    205201 * information about several buffers, among which there is an OBP
    206  * console buffer - this one will be used as the SGCN buffer.
     202 * console buffer -- this one will be used as the SGCN buffer.
    207203 *
    208204 * This function also writes the offset of the SGCN buffer within SRAM
    209205 * under the sram.buffer.offset sysinfo key.
     206 *
    210207 */
    211208static void sgcn_init(void)
     
    248245}
    249246
    250 /**
    251  * Writes a single character to the SGCN (circular) output buffer
    252  * and updates the output write pointer so that SGCN gets to know
     247/** Write a single character to the SGCN output buffer
     248 *
     249 * Write a single character to the SGCN (circular) output buffer
     250 * and update the output write pointer so that SGCN gets to know
    253251 * that the character has been written.
     252 *
    254253 */
    255254static void sgcn_do_putchar(const char c)
     
    286285}
    287286
    288 /**
    289  * SGCN output operation. Prints a single character to the SGCN. Newline
     287/** SGCN output operation
     288 *
     289 * Print a single character to the SGCN. Newline
    290290 * character is converted to CRLF.
    291  */
    292 static void sgcn_putchar(outdev_t *dev, const wchar_t ch, bool silent)
    293 {
    294         if (!silent) {
     291 *
     292 */
     293static void sgcn_putchar(outdev_t *dev, const wchar_t ch)
     294{
     295        if ((!instance->parea.mapped) || (console_override)) {
    295296                spinlock_lock(&instance->output_lock);
    296297               
     
    306307}
    307308
    308 /**
    309  * A public function which initializes input from the Serengeti console.
     309/** Initialize input from the Serengeti console.
     310 *
    310311 */
    311312sgcn_instance_t *sgcnin_init(void)
     
    326327}
    327328
    328 /**
    329  * A public function which initializes output to the Serengeti console.
     329/** Initialize output to the Serengeti console.
     330 *
    330331 */
    331332outdev_t *sgcnout_init(void)
Note: See TracChangeset for help on using the changeset viewer.