cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

audio_template.h (14222B)


      1/*
      2 * QEMU Audio subsystem header
      3 *
      4 * Copyright (c) 2005 Vassili Karpov (malc)
      5 *
      6 * Permission is hereby granted, free of charge, to any person obtaining a copy
      7 * of this software and associated documentation files (the "Software"), to deal
      8 * in the Software without restriction, including without limitation the rights
      9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     10 * copies of the Software, and to permit persons to whom the Software is
     11 * furnished to do so, subject to the following conditions:
     12 *
     13 * The above copyright notice and this permission notice shall be included in
     14 * all copies or substantial portions of the Software.
     15 *
     16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
     19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
     22 * THE SOFTWARE.
     23 */
     24
     25#ifdef DAC
     26#define NAME "playback"
     27#define HWBUF hw->mix_buf
     28#define TYPE out
     29#define HW HWVoiceOut
     30#define SW SWVoiceOut
     31#else
     32#define NAME "capture"
     33#define TYPE in
     34#define HW HWVoiceIn
     35#define SW SWVoiceIn
     36#define HWBUF hw->conv_buf
     37#endif
     38
     39static void glue(audio_init_nb_voices_, TYPE)(AudioState *s,
     40                                              struct audio_driver *drv)
     41{
     42    int max_voices = glue (drv->max_voices_, TYPE);
     43    int voice_size = glue (drv->voice_size_, TYPE);
     44
     45    if (glue (s->nb_hw_voices_, TYPE) > max_voices) {
     46        if (!max_voices) {
     47#ifdef DAC
     48            dolog ("Driver `%s' does not support " NAME "\n", drv->name);
     49#endif
     50        } else {
     51            dolog ("Driver `%s' does not support %d " NAME " voices, max %d\n",
     52                   drv->name,
     53                   glue (s->nb_hw_voices_, TYPE),
     54                   max_voices);
     55        }
     56        glue (s->nb_hw_voices_, TYPE) = max_voices;
     57    }
     58
     59    if (audio_bug(__func__, !voice_size && max_voices)) {
     60        dolog ("drv=`%s' voice_size=0 max_voices=%d\n",
     61               drv->name, max_voices);
     62        glue (s->nb_hw_voices_, TYPE) = 0;
     63    }
     64
     65    if (audio_bug(__func__, voice_size && !max_voices)) {
     66        dolog ("drv=`%s' voice_size=%d max_voices=0\n",
     67               drv->name, voice_size);
     68    }
     69}
     70
     71static void glue (audio_pcm_hw_free_resources_, TYPE) (HW *hw)
     72{
     73    g_free(hw->buf_emul);
     74    g_free (HWBUF);
     75    HWBUF = NULL;
     76}
     77
     78static void glue(audio_pcm_hw_alloc_resources_, TYPE)(HW *hw)
     79{
     80    if (glue(audio_get_pdo_, TYPE)(hw->s->dev)->mixing_engine) {
     81        size_t samples = hw->samples;
     82        if (audio_bug(__func__, samples == 0)) {
     83            dolog("Attempted to allocate empty buffer\n");
     84        }
     85
     86        HWBUF = g_malloc0(sizeof(STSampleBuffer) + sizeof(st_sample) * samples);
     87        HWBUF->size = samples;
     88    } else {
     89        HWBUF = NULL;
     90    }
     91}
     92
     93static void glue (audio_pcm_sw_free_resources_, TYPE) (SW *sw)
     94{
     95    g_free (sw->buf);
     96
     97    if (sw->rate) {
     98        st_rate_stop (sw->rate);
     99    }
    100
    101    sw->buf = NULL;
    102    sw->rate = NULL;
    103}
    104
    105static int glue (audio_pcm_sw_alloc_resources_, TYPE) (SW *sw)
    106{
    107    int samples;
    108
    109    if (!glue(audio_get_pdo_, TYPE)(sw->s->dev)->mixing_engine) {
    110        return 0;
    111    }
    112
    113    samples = ((int64_t) sw->HWBUF->size << 32) / sw->ratio;
    114
    115    sw->buf = audio_calloc(__func__, samples, sizeof(struct st_sample));
    116    if (!sw->buf) {
    117        dolog ("Could not allocate buffer for `%s' (%d samples)\n",
    118               SW_NAME (sw), samples);
    119        return -1;
    120    }
    121
    122#ifdef DAC
    123    sw->rate = st_rate_start (sw->info.freq, sw->hw->info.freq);
    124#else
    125    sw->rate = st_rate_start (sw->hw->info.freq, sw->info.freq);
    126#endif
    127    if (!sw->rate) {
    128        g_free (sw->buf);
    129        sw->buf = NULL;
    130        return -1;
    131    }
    132    return 0;
    133}
    134
    135static int glue (audio_pcm_sw_init_, TYPE) (
    136    SW *sw,
    137    HW *hw,
    138    const char *name,
    139    struct audsettings *as
    140    )
    141{
    142    int err;
    143
    144    audio_pcm_init_info (&sw->info, as);
    145    sw->hw = hw;
    146    sw->active = 0;
    147#ifdef DAC
    148    sw->ratio = ((int64_t) sw->hw->info.freq << 32) / sw->info.freq;
    149    sw->total_hw_samples_mixed = 0;
    150    sw->empty = 1;
    151#else
    152    sw->ratio = ((int64_t) sw->info.freq << 32) / sw->hw->info.freq;
    153#endif
    154
    155    if (sw->info.is_float) {
    156#ifdef DAC
    157        sw->conv = mixeng_conv_float[sw->info.nchannels == 2];
    158#else
    159        sw->clip = mixeng_clip_float[sw->info.nchannels == 2];
    160#endif
    161    } else {
    162#ifdef DAC
    163        sw->conv = mixeng_conv
    164#else
    165        sw->clip = mixeng_clip
    166#endif
    167            [sw->info.nchannels == 2]
    168            [sw->info.is_signed]
    169            [sw->info.swap_endianness]
    170            [audio_bits_to_index(sw->info.bits)];
    171    }
    172
    173    sw->name = g_strdup (name);
    174    err = glue (audio_pcm_sw_alloc_resources_, TYPE) (sw);
    175    if (err) {
    176        g_free (sw->name);
    177        sw->name = NULL;
    178    }
    179    return err;
    180}
    181
    182static void glue (audio_pcm_sw_fini_, TYPE) (SW *sw)
    183{
    184    glue (audio_pcm_sw_free_resources_, TYPE) (sw);
    185    g_free (sw->name);
    186    sw->name = NULL;
    187}
    188
    189static void glue (audio_pcm_hw_add_sw_, TYPE) (HW *hw, SW *sw)
    190{
    191    QLIST_INSERT_HEAD (&hw->sw_head, sw, entries);
    192}
    193
    194static void glue (audio_pcm_hw_del_sw_, TYPE) (SW *sw)
    195{
    196    QLIST_REMOVE (sw, entries);
    197}
    198
    199static void glue (audio_pcm_hw_gc_, TYPE) (HW **hwp)
    200{
    201    HW *hw = *hwp;
    202    AudioState *s = hw->s;
    203
    204    if (!hw->sw_head.lh_first) {
    205#ifdef DAC
    206        audio_detach_capture(hw);
    207#endif
    208        QLIST_REMOVE(hw, entries);
    209        glue(hw->pcm_ops->fini_, TYPE) (hw);
    210        glue(s->nb_hw_voices_, TYPE) += 1;
    211        glue(audio_pcm_hw_free_resources_ , TYPE) (hw);
    212        g_free(hw);
    213        *hwp = NULL;
    214    }
    215}
    216
    217static HW *glue(audio_pcm_hw_find_any_, TYPE)(AudioState *s, HW *hw)
    218{
    219    return hw ? hw->entries.le_next : glue (s->hw_head_, TYPE).lh_first;
    220}
    221
    222static HW *glue(audio_pcm_hw_find_any_enabled_, TYPE)(AudioState *s, HW *hw)
    223{
    224    while ((hw = glue(audio_pcm_hw_find_any_, TYPE)(s, hw))) {
    225        if (hw->enabled) {
    226            return hw;
    227        }
    228    }
    229    return NULL;
    230}
    231
    232static HW *glue(audio_pcm_hw_find_specific_, TYPE)(AudioState *s, HW *hw,
    233                                                   struct audsettings *as)
    234{
    235    while ((hw = glue(audio_pcm_hw_find_any_, TYPE)(s, hw))) {
    236        if (audio_pcm_info_eq (&hw->info, as)) {
    237            return hw;
    238        }
    239    }
    240    return NULL;
    241}
    242
    243static HW *glue(audio_pcm_hw_add_new_, TYPE)(AudioState *s,
    244                                             struct audsettings *as)
    245{
    246    HW *hw;
    247    struct audio_driver *drv = s->drv;
    248
    249    if (!glue (s->nb_hw_voices_, TYPE)) {
    250        return NULL;
    251    }
    252
    253    if (audio_bug(__func__, !drv)) {
    254        dolog ("No host audio driver\n");
    255        return NULL;
    256    }
    257
    258    if (audio_bug(__func__, !drv->pcm_ops)) {
    259        dolog ("Host audio driver without pcm_ops\n");
    260        return NULL;
    261    }
    262
    263    hw = audio_calloc(__func__, 1, glue(drv->voice_size_, TYPE));
    264    if (!hw) {
    265        dolog ("Can not allocate voice `%s' size %d\n",
    266               drv->name, glue (drv->voice_size_, TYPE));
    267        return NULL;
    268    }
    269
    270    hw->s = s;
    271    hw->pcm_ops = drv->pcm_ops;
    272
    273    QLIST_INIT (&hw->sw_head);
    274#ifdef DAC
    275    QLIST_INIT (&hw->cap_head);
    276#endif
    277    if (glue (hw->pcm_ops->init_, TYPE) (hw, as, s->drv_opaque)) {
    278        goto err0;
    279    }
    280
    281    if (audio_bug(__func__, hw->samples <= 0)) {
    282        dolog("hw->samples=%zd\n", hw->samples);
    283        goto err1;
    284    }
    285
    286    if (hw->info.is_float) {
    287#ifdef DAC
    288        hw->clip = mixeng_clip_float[hw->info.nchannels == 2];
    289#else
    290        hw->conv = mixeng_conv_float[hw->info.nchannels == 2];
    291#endif
    292    } else {
    293#ifdef DAC
    294        hw->clip = mixeng_clip
    295#else
    296        hw->conv = mixeng_conv
    297#endif
    298            [hw->info.nchannels == 2]
    299            [hw->info.is_signed]
    300            [hw->info.swap_endianness]
    301            [audio_bits_to_index(hw->info.bits)];
    302    }
    303
    304    glue(audio_pcm_hw_alloc_resources_, TYPE)(hw);
    305
    306    QLIST_INSERT_HEAD (&s->glue (hw_head_, TYPE), hw, entries);
    307    glue (s->nb_hw_voices_, TYPE) -= 1;
    308#ifdef DAC
    309    audio_attach_capture (hw);
    310#endif
    311    return hw;
    312
    313 err1:
    314    glue (hw->pcm_ops->fini_, TYPE) (hw);
    315 err0:
    316    g_free (hw);
    317    return NULL;
    318}
    319
    320AudiodevPerDirectionOptions *glue(audio_get_pdo_, TYPE)(Audiodev *dev)
    321{
    322    switch (dev->driver) {
    323    case AUDIODEV_DRIVER_NONE:
    324        return dev->u.none.TYPE;
    325    case AUDIODEV_DRIVER_ALSA:
    326        return qapi_AudiodevAlsaPerDirectionOptions_base(dev->u.alsa.TYPE);
    327    case AUDIODEV_DRIVER_COREAUDIO:
    328        return qapi_AudiodevCoreaudioPerDirectionOptions_base(
    329            dev->u.coreaudio.TYPE);
    330    case AUDIODEV_DRIVER_DSOUND:
    331        return dev->u.dsound.TYPE;
    332    case AUDIODEV_DRIVER_JACK:
    333        return qapi_AudiodevJackPerDirectionOptions_base(dev->u.jack.TYPE);
    334    case AUDIODEV_DRIVER_OSS:
    335        return qapi_AudiodevOssPerDirectionOptions_base(dev->u.oss.TYPE);
    336    case AUDIODEV_DRIVER_PA:
    337        return qapi_AudiodevPaPerDirectionOptions_base(dev->u.pa.TYPE);
    338    case AUDIODEV_DRIVER_SDL:
    339        return qapi_AudiodevSdlPerDirectionOptions_base(dev->u.sdl.TYPE);
    340    case AUDIODEV_DRIVER_SPICE:
    341        return dev->u.spice.TYPE;
    342    case AUDIODEV_DRIVER_WAV:
    343        return dev->u.wav.TYPE;
    344
    345    case AUDIODEV_DRIVER__MAX:
    346        break;
    347    }
    348    abort();
    349}
    350
    351static HW *glue(audio_pcm_hw_add_, TYPE)(AudioState *s, struct audsettings *as)
    352{
    353    HW *hw;
    354    AudiodevPerDirectionOptions *pdo = glue(audio_get_pdo_, TYPE)(s->dev);
    355
    356    if (!pdo->mixing_engine || pdo->fixed_settings) {
    357        hw = glue(audio_pcm_hw_add_new_, TYPE)(s, as);
    358        if (!pdo->mixing_engine || hw) {
    359            return hw;
    360        }
    361    }
    362
    363    hw = glue(audio_pcm_hw_find_specific_, TYPE)(s, NULL, as);
    364    if (hw) {
    365        return hw;
    366    }
    367
    368    hw = glue(audio_pcm_hw_add_new_, TYPE)(s, as);
    369    if (hw) {
    370        return hw;
    371    }
    372
    373    return glue(audio_pcm_hw_find_any_, TYPE)(s, NULL);
    374}
    375
    376static SW *glue(audio_pcm_create_voice_pair_, TYPE)(
    377    AudioState *s,
    378    const char *sw_name,
    379    struct audsettings *as
    380    )
    381{
    382    SW *sw;
    383    HW *hw;
    384    struct audsettings hw_as;
    385    AudiodevPerDirectionOptions *pdo = glue(audio_get_pdo_, TYPE)(s->dev);
    386
    387    if (pdo->fixed_settings) {
    388        hw_as = audiodev_to_audsettings(pdo);
    389    } else {
    390        hw_as = *as;
    391    }
    392
    393    sw = audio_calloc(__func__, 1, sizeof(*sw));
    394    if (!sw) {
    395        dolog ("Could not allocate soft voice `%s' (%zu bytes)\n",
    396               sw_name ? sw_name : "unknown", sizeof (*sw));
    397        goto err1;
    398    }
    399    sw->s = s;
    400
    401    hw = glue(audio_pcm_hw_add_, TYPE)(s, &hw_as);
    402    if (!hw) {
    403        goto err2;
    404    }
    405
    406    glue (audio_pcm_hw_add_sw_, TYPE) (hw, sw);
    407
    408    if (glue (audio_pcm_sw_init_, TYPE) (sw, hw, sw_name, as)) {
    409        goto err3;
    410    }
    411
    412    return sw;
    413
    414err3:
    415    glue (audio_pcm_hw_del_sw_, TYPE) (sw);
    416    glue (audio_pcm_hw_gc_, TYPE) (&hw);
    417err2:
    418    g_free (sw);
    419err1:
    420    return NULL;
    421}
    422
    423static void glue (audio_close_, TYPE) (SW *sw)
    424{
    425    glue (audio_pcm_sw_fini_, TYPE) (sw);
    426    glue (audio_pcm_hw_del_sw_, TYPE) (sw);
    427    glue (audio_pcm_hw_gc_, TYPE) (&sw->hw);
    428    g_free (sw);
    429}
    430
    431void glue (AUD_close_, TYPE) (QEMUSoundCard *card, SW *sw)
    432{
    433    if (sw) {
    434        if (audio_bug(__func__, !card)) {
    435            dolog ("card=%p\n", card);
    436            return;
    437        }
    438
    439        glue (audio_close_, TYPE) (sw);
    440    }
    441}
    442
    443SW *glue (AUD_open_, TYPE) (
    444    QEMUSoundCard *card,
    445    SW *sw,
    446    const char *name,
    447    void *callback_opaque ,
    448    audio_callback_fn callback_fn,
    449    struct audsettings *as
    450    )
    451{
    452    AudioState *s;
    453    AudiodevPerDirectionOptions *pdo;
    454
    455    if (audio_bug(__func__, !card || !name || !callback_fn || !as)) {
    456        dolog ("card=%p name=%p callback_fn=%p as=%p\n",
    457               card, name, callback_fn, as);
    458        goto fail;
    459    }
    460
    461    s = card->state;
    462    pdo = glue(audio_get_pdo_, TYPE)(s->dev);
    463
    464    ldebug ("open %s, freq %d, nchannels %d, fmt %d\n",
    465            name, as->freq, as->nchannels, as->fmt);
    466
    467    if (audio_bug(__func__, audio_validate_settings(as))) {
    468        audio_print_settings (as);
    469        goto fail;
    470    }
    471
    472    if (audio_bug(__func__, !s->drv)) {
    473        dolog ("Can not open `%s' (no host audio driver)\n", name);
    474        goto fail;
    475    }
    476
    477    if (sw && audio_pcm_info_eq (&sw->info, as)) {
    478        return sw;
    479    }
    480
    481    if (!pdo->fixed_settings && sw) {
    482        glue (AUD_close_, TYPE) (card, sw);
    483        sw = NULL;
    484    }
    485
    486    if (sw) {
    487        HW *hw = sw->hw;
    488
    489        if (!hw) {
    490            dolog ("Internal logic error voice `%s' has no hardware store\n",
    491                   SW_NAME (sw));
    492            goto fail;
    493        }
    494
    495        glue (audio_pcm_sw_fini_, TYPE) (sw);
    496        if (glue (audio_pcm_sw_init_, TYPE) (sw, hw, name, as)) {
    497            goto fail;
    498        }
    499    } else {
    500        sw = glue(audio_pcm_create_voice_pair_, TYPE)(s, name, as);
    501        if (!sw) {
    502            dolog ("Failed to create voice `%s'\n", name);
    503            return NULL;
    504        }
    505    }
    506
    507    sw->card = card;
    508    sw->vol = nominal_volume;
    509    sw->callback.fn = callback_fn;
    510    sw->callback.opaque = callback_opaque;
    511
    512#ifdef DEBUG_AUDIO
    513    dolog ("%s\n", name);
    514    audio_pcm_print_info ("hw", &sw->hw->info);
    515    audio_pcm_print_info ("sw", &sw->info);
    516#endif
    517
    518    return sw;
    519
    520 fail:
    521    glue (AUD_close_, TYPE) (card, sw);
    522    return NULL;
    523}
    524
    525int glue (AUD_is_active_, TYPE) (SW *sw)
    526{
    527    return sw ? sw->active : 0;
    528}
    529
    530void glue (AUD_init_time_stamp_, TYPE) (SW *sw, QEMUAudioTimeStamp *ts)
    531{
    532    if (!sw) {
    533        return;
    534    }
    535
    536    ts->old_ts = sw->hw->ts_helper;
    537}
    538
    539uint64_t glue (AUD_get_elapsed_usec_, TYPE) (SW *sw, QEMUAudioTimeStamp *ts)
    540{
    541    uint64_t delta, cur_ts, old_ts;
    542
    543    if (!sw) {
    544        return 0;
    545    }
    546
    547    cur_ts = sw->hw->ts_helper;
    548    old_ts = ts->old_ts;
    549    /* dolog ("cur %" PRId64 " old %" PRId64 "\n", cur_ts, old_ts); */
    550
    551    if (cur_ts >= old_ts) {
    552        delta = cur_ts - old_ts;
    553    } else {
    554        delta = UINT64_MAX - old_ts + cur_ts;
    555    }
    556
    557    if (!delta) {
    558        return 0;
    559    }
    560
    561    return muldiv64 (delta, sw->hw->info.freq, 1000000);
    562}
    563
    564#undef TYPE
    565#undef HW
    566#undef SW
    567#undef HWBUF
    568#undef NAME